mirror of
https://github.com/MatMasIt/gnome-therminal-autotheme.git
synced 2025-04-20 18:45:27 +02:00
first commit
This commit is contained in:
commit
327959e0fa
60
README.md
Normal file
60
README.md
Normal file
@ -0,0 +1,60 @@
|
||||
# GNOME Terminal Auto Theme Sync
|
||||
|
||||

|
||||
|
||||
Automatically sync your GNOME Terminal theme with your system's light/dark mode preferences.
|
||||
|
||||
## Features
|
||||
|
||||
- 🌓 Automatic theme switching between light and dark modes
|
||||
- ⚡ Instant theme application when system preference changes
|
||||
- 🔄 Background process that monitors system theme changes
|
||||
- 🛠️ Easy installation and uninstallation
|
||||
|
||||
## Installation
|
||||
|
||||
1. **Download the project files**:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/MatMasIt/gnome-terminal-autotheme.git
|
||||
cd gnome-terminal-autotheme
|
||||
```
|
||||
|
||||
2. **Run the installer**:
|
||||
|
||||
```bash
|
||||
./install.sh
|
||||
```
|
||||
|
||||
3. **Follow the prompts** to complete installation.
|
||||
|
||||
The installer will:
|
||||
- Copy necessary files
|
||||
- Set up autostart entry
|
||||
- Start the theme sync service
|
||||
|
||||
## Uninstallation
|
||||
|
||||
To remove the auto theme sync, simply run the installer again.
|
||||
|
||||
You'll be prompted to choose:
|
||||
- Remove just the autostart entry or the whole installation
|
||||
- Whether to keep your terminal in light or dark mode after uninstall
|
||||
|
||||
## Requirements
|
||||
|
||||
- GNOME Desktop Environment (tested on GNOME 40+)
|
||||
- GNOME Terminal
|
||||
- Bash 4.0+
|
||||
|
||||
## Configuration
|
||||
|
||||
Advanced users can edit the theme definitions in: [sync-terminal-theme.sh](sync-terminal-theme.sh)
|
||||
|
||||
## Contributing
|
||||
|
||||
Contributions are welcome! Please open an issue or pull request.
|
||||
|
||||
## License
|
||||
|
||||
MIT License - See [LICENSE](LICENSE) file for details
|
7
gnome-terminal-autotheme.desktop
Normal file
7
gnome-terminal-autotheme.desktop
Normal file
@ -0,0 +1,7 @@
|
||||
[Desktop Entry]
|
||||
Type=Application
|
||||
Exec=PATH/sync-terminal-theme.sh
|
||||
Hidden=false
|
||||
NoDisplay=false
|
||||
X-GNOME-Autostart-enabled=true
|
||||
Name=GNOME Terminal Theme Sync
|
305
install.sh
Executable file
305
install.sh
Executable file
@ -0,0 +1,305 @@
|
||||
#!/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
|
54
sync-terminal-theme.sh
Executable file
54
sync-terminal-theme.sh
Executable file
@ -0,0 +1,54 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Get the default profile UUID
|
||||
PROFILE_ID=$(gsettings get org.gnome.Terminal.ProfilesList default | tr -d \')
|
||||
PROFILE_PATH="/org/gnome/terminal/legacy/profiles:/:$PROFILE_ID"
|
||||
|
||||
# Define themes
|
||||
set_dark_theme() {
|
||||
gsettings set org.gnome.Terminal.Legacy.Settings theme-variant 'dark'
|
||||
dconf write $PROFILE_PATH/use-theme-colors false
|
||||
dconf write $PROFILE_PATH/foreground-color "'#d4d4d4'"
|
||||
dconf write $PROFILE_PATH/background-color "'#1e1e1e'"
|
||||
dconf write $PROFILE_PATH/palette "['#1e1e1e', '#f44747', '#619955', '#ffaf00', '#85dfff', '#d27bff', '#4EC9B0', '#d4d4d4', '#808080', '#f44747', '#619955', '#ffaf00', '#85dfff', '#d27bff', '#4EC9B0', '#ffffff']"
|
||||
dconf write $PROFILE_PATH/cursor-color "'#d4d4d4'"
|
||||
}
|
||||
|
||||
set_light_theme() {
|
||||
gsettings set org.gnome.Terminal.Legacy.Settings theme-variant 'light'
|
||||
dconf write $PROFILE_PATH/use-theme-colors false
|
||||
dconf write $PROFILE_PATH/foreground-color "'#000000'"
|
||||
dconf write $PROFILE_PATH/background-color "'#ffffff'"
|
||||
dconf write $PROFILE_PATH/palette "['#000000', '#cc0000', '#4e9a06', '#c4a000', '#3465a4', '#75507b', '#06989a', '#d3d7cf', '#555753', '#ef2929', '#8ae234', '#fce94f', '#729fcf', '#ad7fa8', '#34e2e2', '#eeeeec']"
|
||||
dconf write $PROFILE_PATH/cursor-color "'#000000'"
|
||||
}
|
||||
|
||||
update_terminal_theme() {
|
||||
SCHEME=$(gsettings get org.gnome.desktop.interface color-scheme)
|
||||
|
||||
if [[ "$SCHEME" == *"dark"* ]]; then
|
||||
set_dark_theme
|
||||
else
|
||||
set_light_theme
|
||||
fi
|
||||
}
|
||||
|
||||
# Check for manual arguments (light or dark)
|
||||
if [[ "${1:-}" == "light" ]]; then
|
||||
set_light_theme
|
||||
echo "[sync-script] Applied light theme manually."
|
||||
exit 0
|
||||
elif [[ "${1:-}" == "dark" ]]; then
|
||||
set_dark_theme
|
||||
echo "[sync-script] Applied dark theme manually."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Run once immediately to apply based on the current GNOME theme
|
||||
update_terminal_theme
|
||||
|
||||
# Monitor and auto-update GNOME theme changes
|
||||
echo "[sync-script] Monitoring GNOME theme changes..."
|
||||
gsettings monitor org.gnome.desktop.interface color-scheme | while read -r; do
|
||||
update_terminal_theme
|
||||
done
|
Loading…
x
Reference in New Issue
Block a user