Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 56 additions & 7 deletions bin/omarchy-theme-install
Original file line number Diff line number Diff line change
Expand Up @@ -17,23 +17,72 @@ if [[ -z $REPO_URL ]]; then
fi

THEMES_DIR="$HOME/.config/omarchy/themes"
if ! mkdir -p "$THEMES_DIR"; then
echo "Error: Failed to create themes directory."
exit 1
fi

# Strip user@host: prefix from scp-style SSH URLs so basename sees just the path
REPO_PATH="$REPO_URL"
[[ $REPO_PATH != *"://"* && $REPO_PATH == *:*/* ]] && REPO_PATH="${REPO_PATH#*:}"
THEME_NAME=$(basename "$REPO_PATH" .git | sed -E 's/^omarchy-//; s/-theme$//' | tr '[:upper:]' '[:lower:]')
THEME_PATH="$THEMES_DIR/$THEME_NAME"

# Remove existing theme if present
if [[ -d $THEME_PATH ]]; then
rm -rf "$THEME_PATH"
if ! STAGING_DIR=$(mktemp -d "$THEMES_DIR/.theme-install.XXXXXX"); then
echo "Error: Failed to create theme staging directory."
exit 1
fi
STAGED_THEME_PATH="$STAGING_DIR/$THEME_NAME"
if ! BACKUP_THEME_DIR=$(mktemp -d "$THEMES_DIR/.theme-backup.XXXXXX"); then
rm -rf "$STAGING_DIR"
echo "Error: Failed to create theme backup directory."
exit 1
fi
BACKUP_THEME_PATH="$BACKUP_THEME_DIR/$THEME_NAME"
PRESERVE_BACKUP=0

# Clone the repo directly to ~/.config/omarchy/themes
if ! git clone "$REPO_URL" "$THEME_PATH"; then
cleanup() {
rm -rf "$STAGING_DIR"
(( PRESERVE_BACKUP )) || rm -rf "$BACKUP_THEME_DIR"
}
trap cleanup EXIT

# Clone into a staging directory so a failed clone cannot remove the installed theme
if ! git clone "$REPO_URL" "$STAGED_THEME_PATH"; then
echo "Error: Failed to clone theme repo."
exit 1
fi

if [[ -e $THEME_PATH ]] && ! mv "$THEME_PATH" "$BACKUP_THEME_PATH"; then
echo "Error: Failed to stage the existing theme."
exit 1
fi

if ! mv "$STAGED_THEME_PATH" "$THEME_PATH"; then
if [[ -e $BACKUP_THEME_PATH ]] && ! mv "$BACKUP_THEME_PATH" "$THEME_PATH"; then
echo "Error: Failed to install theme repo and restore the existing theme."
exit 1
fi
echo "Error: Failed to install theme repo."
exit 1
fi

# Apply the new theme with omarchy-theme-set
omarchy-theme-set $THEME_NAME
if ! omarchy-theme-set "$THEME_NAME"; then
if [[ -e $BACKUP_THEME_PATH ]]; then
FAILED_THEME_PATH="$BACKUP_THEME_DIR/failed-$THEME_NAME"
if mv "$THEME_PATH" "$FAILED_THEME_PATH" && mv "$BACKUP_THEME_PATH" "$THEME_PATH"; then
PRESERVE_BACKUP=1
echo "Error: Failed to apply installed theme; the previous theme was restored." >&2
echo "The failed theme remains at $FAILED_THEME_PATH for inspection." >&2
else
PRESERVE_BACKUP=1
echo "Error: Failed to apply installed theme and restore the previous theme." >&2
echo "The backup remains at $BACKUP_THEME_PATH." >&2
fi
else
echo "Error: Failed to apply installed theme; the new theme remains installed for retry." >&2
fi
exit 1
fi

rm -rf "$BACKUP_THEME_PATH"
142 changes: 114 additions & 28 deletions bin/omarchy-theme-set
Original file line number Diff line number Diff line change
Expand Up @@ -9,65 +9,151 @@ if [[ -z $1 ]]; then
exit 1
fi

CURRENT_THEME_PATH="$HOME/.config/omarchy/current/theme"
NEXT_THEME_PATH="$HOME/.config/omarchy/current/next-theme"
CURRENT_THEME_DIR="$HOME/.config/omarchy/current"
CURRENT_THEME_PATH="$CURRENT_THEME_DIR/theme"
USER_THEMES_PATH="$HOME/.config/omarchy/themes"
OMARCHY_THEMES_PATH="$OMARCHY_PATH/themes"

if ! mkdir -p "$CURRENT_THEME_DIR"; then
echo "Failed to create theme state directory"
exit 1
fi

if ! NEXT_THEME_PATH=$(mktemp -d "$CURRENT_THEME_DIR/next-theme.XXXXXX"); then
echo "Failed to create theme staging directory"
exit 1
fi

if ! PREVIOUS_THEME_DIR=$(mktemp -d "$CURRENT_THEME_DIR/previous-theme.XXXXXX"); then
rm -rf "$NEXT_THEME_PATH"
echo "Failed to create theme backup directory"
exit 1
fi
PREVIOUS_THEME_PATH="$PREVIOUS_THEME_DIR/theme"
CURRENT_THEME_STAGED=0
POST_THEME_FAILURES=()

cleanup() {
local exit_status=$?

if (( CURRENT_THEME_STAGED )) && [[ ! -e $CURRENT_THEME_PATH ]] && [[ -e $PREVIOUS_THEME_PATH ]]; then
if mv "$PREVIOUS_THEME_PATH" "$CURRENT_THEME_PATH"; then
echo "Restored the previous theme after interrupted activation" >&2
else
echo "Failed to restore the previous theme after interrupted activation" >&2
exit_status=1
fi
fi

rm -rf "$NEXT_THEME_PATH" "$PREVIOUS_THEME_DIR"
return "$exit_status"
}
trap cleanup EXIT
trap 'exit 130' INT
trap 'exit 143' TERM

THEME_NAME=$(echo "$1" | sed -E 's/<[^>]+>//g' | tr '[:upper:]' '[:lower:]' | tr ' ' '-')

if [[ ! -d $OMARCHY_THEMES_PATH/$THEME_NAME ]] && [[ ! -d $USER_THEMES_PATH/$THEME_NAME ]]; then
echo "Theme '$THEME_NAME' does not exist"
exit 1
fi

# Setup clean next theme directory (for atomic theme config swapping)
rm -rf "$NEXT_THEME_PATH"
# Setup a unique staging directory for atomic theme config swapping
mkdir -p "$NEXT_THEME_PATH"

# Copy official theme first, then overlay user customizations 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
copy_theme_files() {
local source="$1"
[[ -d $source ]] || return 0
cp -a "$source"/. "$NEXT_THEME_PATH/"
}

if ! copy_theme_files "$OMARCHY_THEMES_PATH/$THEME_NAME" ||
! copy_theme_files "$USER_THEMES_PATH/$THEME_NAME"; then
echo "Failed to copy theme '$THEME_NAME'"
exit 1
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
omarchy-theme-colors-from-alacritty "$NEXT_THEME_PATH"
if ! omarchy-theme-colors-from-alacritty "$NEXT_THEME_PATH"; then
echo "Failed to generate theme colors for '$THEME_NAME'"
exit 1
fi
fi

# Generate dynamic configs
omarchy-theme-set-templates
if ! OMARCHY_THEME_STAGE_DIR="$NEXT_THEME_PATH" omarchy-theme-set-templates; then
echo "Failed to generate themed configuration for '$THEME_NAME'"
exit 1
fi

# Swap next theme in as current
rm -rf "$CURRENT_THEME_PATH"
mv "$NEXT_THEME_PATH" "$CURRENT_THEME_PATH"
# Swap the staged theme in as current, retaining the old theme until the move succeeds
if [[ -e $CURRENT_THEME_PATH ]]; then
CURRENT_THEME_STAGED=1
if ! mv "$CURRENT_THEME_PATH" "$PREVIOUS_THEME_PATH"; then
CURRENT_THEME_STAGED=0
echo "Failed to stage the current theme for replacement"
exit 1
fi
fi

if ! mv "$NEXT_THEME_PATH" "$CURRENT_THEME_PATH"; then
if [[ -e $PREVIOUS_THEME_PATH ]]; then
if ! mv "$PREVIOUS_THEME_PATH" "$CURRENT_THEME_PATH"; then
echo "Failed to activate theme '$THEME_NAME' and restore the previous theme"
exit 1
fi
fi
echo "Failed to activate theme '$THEME_NAME'"
exit 1
fi
CURRENT_THEME_STAGED=0

# Store theme name for reference
echo "$THEME_NAME" >"$HOME/.config/omarchy/current/theme.name"
if ! echo "$THEME_NAME" >"$HOME/.config/omarchy/current/theme.name"; then
POST_THEME_FAILURES+=("recording the current theme")
fi

run_optional() {
local description="$1"
shift

if ! "$@"; then
POST_THEME_FAILURES+=("$description")
echo "Warning: $description failed" >&2
fi
}

# Change background with theme
if [[ $OMARCHY_THEME_SKIP_BACKGROUND != "1" ]]; then
omarchy-theme-bg-next
run_optional "changing the theme background" omarchy-theme-bg-next
fi

# Restart components to apply new theme
if pgrep -x waybar >/dev/null; then
omarchy-restart-waybar
run_optional "restarting Waybar" omarchy-restart-waybar
fi
omarchy-restart-swayosd
omarchy-restart-terminal
omarchy-restart-hyprctl
omarchy-restart-btop
omarchy-restart-opencode
omarchy-restart-mako
omarchy-restart-helix
run_optional "restarting SwayOSD" omarchy-restart-swayosd
run_optional "restarting the terminal" omarchy-restart-terminal
run_optional "restarting Hyprland helpers" omarchy-restart-hyprctl
run_optional "restarting btop" omarchy-restart-btop
run_optional "restarting Opencode" omarchy-restart-opencode
run_optional "restarting Mako" omarchy-restart-mako
run_optional "restarting Helix" omarchy-restart-helix

# Change app-specific themes
omarchy-theme-set-foot
omarchy-theme-set-gnome
omarchy-theme-set-browser
omarchy-theme-set-vscode
omarchy-theme-set-obsidian
omarchy-theme-set-keyboard
run_optional "updating Foot theme" omarchy-theme-set-foot
run_optional "updating GNOME theme" omarchy-theme-set-gnome
run_optional "updating browser theme" omarchy-theme-set-browser
run_optional "updating VS Code theme" omarchy-theme-set-vscode
run_optional "updating Obsidian theme" omarchy-theme-set-obsidian
run_optional "updating keyboard theme" omarchy-theme-set-keyboard

# Call hook on theme set
omarchy-hook theme-set "$THEME_NAME" >/dev/null
run_optional "running the theme-set hook" omarchy-hook theme-set "$THEME_NAME"

if (( ${#POST_THEME_FAILURES[@]} > 0 )); then
echo "Theme '$THEME_NAME' activated with ${#POST_THEME_FAILURES[@]} integration warning(s)." >&2
fi
13 changes: 10 additions & 3 deletions bin/omarchy-theme-set-templates
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

TEMPLATES_DIR="$OMARCHY_PATH/default/themed"
USER_TEMPLATES_DIR="$HOME/.config/omarchy/themed"
NEXT_THEME_DIR="$HOME/.config/omarchy/current/next-theme"
NEXT_THEME_DIR="${OMARCHY_THEME_STAGE_DIR:-$HOME/.config/omarchy/current/next-theme}"
COLORS_FILE="$NEXT_THEME_DIR/colors.toml"

# Convert hex color to decimal RGB (e.g., "#1e1e2e" -> "30,30,46")
Expand All @@ -16,7 +16,10 @@ hex_to_rgb() {

# Only generate dynamic templates for themes with a colors.toml definition
if [[ -f $COLORS_FILE ]]; then
sed_script=$(mktemp)
if ! sed_script=$(mktemp); then
echo "Failed to create theme template staging file"
exit 1
fi

while IFS='=' read -r key value; do
key="${key//[\"\' ]/}" # strip quotes and spaces from key
Expand All @@ -41,7 +44,11 @@ if [[ -f $COLORS_FILE ]]; then

# Don't overwrite configs already exists in the output directory (copied from theme specific folder)
if [[ ! -f $output_path ]]; then
sed -f "$sed_script" "$tpl" >"$output_path"
if ! sed -f "$sed_script" "$tpl" >"$output_path"; then
rm -f "$sed_script"
echo "Failed to generate themed file '$output_path'"
exit 1
fi
fi
done

Expand Down
Loading