mirror of
https://github.com/MatMasIt/gnome-therminal-autotheme.git
synced 2025-04-20 18:45:27 +02:00
305 lines
8.6 KiB
Bash
Executable File
305 lines
8.6 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
|
|
set -euo pipefail
|
|
IFS=$'\n\t'
|
|
|
|
# Constants
|
|
readonly DEFAULT_DIR="$HOME/.local/share/gnome-terminal-autotheme"
|
|
readonly DESKTOP_FILE_NAME="gnome-terminal-autotheme.desktop"
|
|
readonly AUTOSTART_DIR="$HOME/.config/autostart"
|
|
readonly AUTOSTART_TARGET="$AUTOSTART_DIR/$DESKTOP_FILE_NAME"
|
|
readonly SCRIPT_NAME="sync-terminal-theme.sh"
|
|
readonly VERSION="1.1.0"
|
|
|
|
# Colors for output
|
|
readonly RED='\033[0;31m'
|
|
readonly GREEN='\033[0;32m'
|
|
readonly YELLOW='\033[0;33m'
|
|
readonly BLUE='\033[0;34m'
|
|
readonly NC='\033[0m' # No Color
|
|
|
|
# Utility functions
|
|
error() {
|
|
echo -e "${RED}[ERROR]${NC} $1" >&2
|
|
}
|
|
|
|
warning() {
|
|
echo -e "${YELLOW}[WARNING]${NC} $1"
|
|
}
|
|
|
|
info() {
|
|
echo -e "${BLUE}[INFO]${NC} $1"
|
|
}
|
|
|
|
success() {
|
|
echo -e "${GREEN}[SUCCESS]${NC} $1"
|
|
}
|
|
|
|
check_installed() {
|
|
command -v "$1" >/dev/null 2>&1
|
|
}
|
|
|
|
stop_existing_processes() {
|
|
local pids
|
|
pids=$(pgrep -f "$SCRIPT_NAME" || true)
|
|
|
|
if [[ -n "$pids" ]]; then
|
|
info "Stopping existing theme sync processes..."
|
|
for pid in $pids; do
|
|
if kill -0 "$pid" 2>/dev/null; then
|
|
kill "$pid" && info "Stopped process $pid" || warning "Failed to stop process $pid"
|
|
fi
|
|
done
|
|
# Wait a moment for processes to terminate
|
|
sleep 0.5
|
|
fi
|
|
}
|
|
|
|
validate_path() {
|
|
local path="$1"
|
|
[[ -z "$path" ]] && { error "Path cannot be empty"; return 1; }
|
|
[[ "$path" == "/" ]] && { error "Cannot use root directory"; return 1; }
|
|
[[ "$path" =~ ^/etc ]] && { error "System directories not allowed"; return 1; }
|
|
return 0
|
|
}
|
|
|
|
is_gnome() {
|
|
[[ "$XDG_CURRENT_DESKTOP" =~ GNOME|gnome ]] || check_installed gnome-session
|
|
}
|
|
|
|
start_sync() {
|
|
info "Running sync script now in the background..."
|
|
nohup bash "$INSTALL_DIR/$SCRIPT_NAME" >/dev/null 2>&1 &
|
|
disown
|
|
success "Theme sync script running in background (PID: $!)"
|
|
}
|
|
|
|
|
|
check_integrity() {
|
|
local install_dir="${1:-$DEFAULT_DIR}"
|
|
info "Checking installation integrity in: $install_dir"
|
|
|
|
local desktop_file="$AUTOSTART_TARGET"
|
|
local target_exec
|
|
|
|
if [[ ! -f "$desktop_file" ]]; then
|
|
error "Autostart desktop entry not found: $desktop_file"
|
|
return 1
|
|
fi
|
|
|
|
# Extract Exec path from .desktop file
|
|
target_exec=$(grep -oP '^Exec=\K.+' "$desktop_file" | head -n1)
|
|
if [[ -z "$target_exec" ]]; then
|
|
error "No Exec entry found in desktop file"
|
|
return 1
|
|
fi
|
|
|
|
if [[ ! -f "$target_exec" ]]; then
|
|
error "Script file referenced in .desktop does not exist: $target_exec"
|
|
return 1
|
|
fi
|
|
|
|
if [[ ! -x "$target_exec" ]]; then
|
|
error "Script file is not executable: $target_exec"
|
|
return 1
|
|
fi
|
|
|
|
if ! head -n 1 "$target_exec" | grep -qE '^#!.*/bash'; then
|
|
error "Script does not start with a valid bash shebang: $target_exec"
|
|
return 1
|
|
fi
|
|
|
|
success "All basic integrity checks passed"
|
|
}
|
|
|
|
|
|
uninstall() {
|
|
local install_dir="$1"
|
|
local uninstall_choice="${2:-autostart}"
|
|
local theme_choice="${3:-d}"
|
|
|
|
info "Starting uninstallation..."
|
|
|
|
# Kill running process
|
|
stop_existing_processes
|
|
|
|
# Remove autostart entry
|
|
if [[ -f "$AUTOSTART_TARGET" ]]; then
|
|
rm -f -- "$AUTOSTART_TARGET" && success "Autostart entry removed" || error "Failed to remove autostart entry"
|
|
fi
|
|
|
|
# Apply final theme
|
|
case "${theme_choice,,}" in
|
|
l|light)
|
|
bash "$install_dir/$SCRIPT_NAME" light && success "Applied light theme" || error "Failed to apply light theme"
|
|
;;
|
|
d|dark)
|
|
bash "$install_dir/$SCRIPT_NAME" dark && success "Applied dark theme" || error "Failed to apply dark theme"
|
|
;;
|
|
*)
|
|
warning "No theme change applied"
|
|
;;
|
|
esac
|
|
|
|
# Remove installation directory if requested
|
|
if [[ "$uninstall_choice" =~ ^whole$ ]]; then
|
|
if [[ -d "$install_dir" ]]; then
|
|
rm -rf -- "$install_dir" && success "Installation directory removed" || error "Failed to remove directory"
|
|
else
|
|
warning "Installation directory not found"
|
|
fi
|
|
fi
|
|
|
|
success "Uninstallation complete"
|
|
}
|
|
|
|
install() {
|
|
|
|
local reinstall="${1:-false}"
|
|
local provided_path="${2:-}"
|
|
|
|
info "Starting installation..."
|
|
|
|
stop_existing_processes
|
|
|
|
# Check for gnome-terminal
|
|
if ! check_installed gnome-terminal; then
|
|
warning "gnome-terminal not found"
|
|
read -rp "Continue anyway? [y/N]: " proceed_terminal
|
|
[[ "${proceed_terminal,,}" =~ ^y ]] || { error "Aborted"; exit 1; }
|
|
fi
|
|
|
|
# Check for GNOME
|
|
if ! is_gnome; then
|
|
warning "GNOME not detected"
|
|
read -rp "Continue anyway? [y/N]: " proceed_gnome
|
|
[[ "${proceed_gnome,,}" =~ ^y ]] || { error "Aborted"; exit 1; }
|
|
fi
|
|
|
|
# Use provided path or prompt user
|
|
if [[ -n "$provided_path" ]]; then
|
|
INSTALL_DIR=$(realpath -m "$provided_path")
|
|
else
|
|
read -rp "Enter install path [default: $DEFAULT_DIR]: " install_dir
|
|
INSTALL_DIR=$(realpath -m "${install_dir:-$DEFAULT_DIR}")
|
|
fi
|
|
|
|
if ! validate_path "$INSTALL_DIR"; then
|
|
error "Invalid install path: $INSTALL_DIR"
|
|
exit 1
|
|
fi
|
|
|
|
# Create directory
|
|
mkdir -p -- "$INSTALL_DIR" || { error "Failed to create directory"; exit 1; }
|
|
|
|
# Verify source files exist
|
|
if [[ ! -f "$SCRIPT_NAME" || ! -f "$DESKTOP_FILE_NAME" ]]; then
|
|
error "Missing required files: $SCRIPT_NAME and $DESKTOP_FILE_NAME must be in current directory"
|
|
exit 1
|
|
fi
|
|
|
|
# Copy files
|
|
cp -- "$SCRIPT_NAME" "$INSTALL_DIR/" || { error "Failed to copy script"; exit 1; }
|
|
cp -- "$DESKTOP_FILE_NAME" "$INSTALL_DIR/" || { error "Failed to copy desktop file"; exit 1; }
|
|
|
|
# Make script executable
|
|
chmod +x "$INSTALL_DIR/$SCRIPT_NAME" || { error "Failed to make script executable"; exit 1; }
|
|
|
|
# Create autostart entry
|
|
mkdir -p -- "$AUTOSTART_DIR" || { error "Failed to create autostart directory"; exit 1; }
|
|
|
|
# Escape path for sed
|
|
local escaped_path=$(printf '%q' "$INSTALL_DIR/$SCRIPT_NAME")
|
|
sed "s|Exec=.*|Exec=$escaped_path|" "$INSTALL_DIR/$DESKTOP_FILE_NAME" > "$AUTOSTART_TARGET" || {
|
|
error "Failed to create autostart entry"
|
|
exit 1
|
|
}
|
|
|
|
success "Installation complete"
|
|
success "Script installed to: $INSTALL_DIR"
|
|
success "Autostart entry created: $AUTOSTART_TARGET"
|
|
|
|
# Start sync process
|
|
start_sync
|
|
}
|
|
|
|
main() {
|
|
echo -e "${BLUE}=== GNOME Terminal Auto Theme Sync v$VERSION ===${NC}"
|
|
|
|
# Check if installed
|
|
if [[ -f "$AUTOSTART_TARGET" ]]; then
|
|
local old_install_dir=$(grep -oP 'Exec=\K.+' "$AUTOSTART_TARGET" | sed "s|/$SCRIPT_NAME||")
|
|
|
|
if [[ -z "$old_install_dir" || ! -d "$old_install_dir" ]]; then
|
|
warning "Could not determine valid install path from autostart entry (you may want to look into it)"
|
|
info "Fallback to default installation directory"
|
|
old_install_dir="$DEFAULT_DIR"
|
|
if [[ ! -d "$old_install_dir" ]]; then
|
|
error "Default install directory does not exist: $old_install_dir"
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
|
|
|
|
info "Theme watcher already installed at: $old_install_dir"
|
|
|
|
read -rp "Do you want to (u)ninstall, (r)einstall or check (i)ntegrity? [u/r/i/N]: " choice
|
|
case "${choice,,}" in
|
|
u)
|
|
# Loop until a valid choice is entered for uninstall
|
|
while true; do
|
|
read -rp "Uninstall (w)hole installation or (a)utostart entry? [w/a]: " uninstall_choice
|
|
case "${uninstall_choice,,}" in
|
|
a) uninstall_choice="autostart"; break ;;
|
|
w) uninstall_choice="whole"; break ;;
|
|
esac
|
|
echo "Invalid choice, please enter 'w' for whole or 'a' for autostart."
|
|
done
|
|
|
|
# Loop until a valid choice is entered for theme selection
|
|
while true; do
|
|
read -rp "Set terminal theme to (l)ight or (d)ark after uninstall? [l/d]: " theme_choice
|
|
case "${theme_choice,,}" in
|
|
l) theme_choice="l"; break ;;
|
|
d) theme_choice="d"; break ;;
|
|
esac
|
|
echo "Invalid choice, please enter 'l' for light or 'd' for dark."
|
|
done
|
|
|
|
uninstall "$old_install_dir" "$uninstall_choice" "$theme_choice"
|
|
exit 0
|
|
;;
|
|
r)
|
|
read -rp "Enter new install path [default: $DEFAULT_DIR]: " install_dir
|
|
INSTALL_DIR="${install_dir:-$DEFAULT_DIR}"
|
|
INSTALL_DIR=$(realpath -m "$INSTALL_DIR")
|
|
|
|
if [[ "$INSTALL_DIR" != "$old_install_dir" ]]; then
|
|
read -rp "The new install path is different from the old one ($old_install_dir). Remove old directory? [y/N]: " remove_old
|
|
if [[ "${remove_old,,}" =~ ^y ]]; then
|
|
if [[ -d "$old_install_dir" ]]; then
|
|
rm -rf -- "$old_install_dir" && success "Old installation directory removed" || error "Failed to remove old directory"
|
|
else
|
|
warning "Old installation directory not found"
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
install true "$INSTALL_DIR"
|
|
;;
|
|
i)
|
|
check_integrity "$old_install_dir"
|
|
exit $?
|
|
;;
|
|
*)
|
|
info "No changes made"
|
|
exit 0
|
|
;;
|
|
esac
|
|
else
|
|
install
|
|
fi
|
|
}
|
|
|
|
main |