Distribution-agnostic provisioning script that sets up a new Linux machine (Detected via lib/distro.sh - supports Debian/Ubuntu/Pop and Fedora families). 13 stages covering: - System packages, external repos, toolchains (nvm, uv, Python) - Shell config (zsh, oh-my-zsh, p10k), git, SSH - Custom uv tools from ~40 git repos - Desktop config (keybindings, hotkeys, ghostty, fonts) - Docker, system tweaks, browser/app installs - Custom systemd user services (porridge, swayidle, mempi-sync, etc.) - API keys loaded from Bitwarden at shell startup
200 lines
8.4 KiB
Bash
200 lines
8.4 KiB
Bash
#!/usr/bin/env bash
|
|
# ===========================================================================
|
|
# Stage 09: Desktop Configuration
|
|
# Keybindings, hotkey scripts, Ghostty, fonts, and desktop theme.
|
|
# ===========================================================================
|
|
# On Pop!_OS, Julian uses COSMIC desktop (Rust-based, System76's own DE).
|
|
# Fedora ships with GNOME by default. This stage provides keybinding config
|
|
# for both GNOME (via gsettings) and a fallback swhkd/keyd approach.
|
|
#
|
|
# If you install a different DE (KDE, COSMIC via COPR, Sway/Hyprland),
|
|
# adjust this stage accordingly.
|
|
# ===========================================================================
|
|
|
|
CONFIG_DIR="${SCRIPT_DIR:-$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)}/config"
|
|
|
|
# Detect desktop environment
|
|
DE="${XDG_CURRENT_DESKTOP:-unknown}"
|
|
|
|
# ===========================================================================
|
|
# 1. Hotkey Scripts (from hotkeys repo)
|
|
# ===========================================================================
|
|
# These are shell scripts that use selected text for quick actions.
|
|
# They rely on: wl-clipboard, wtype, wofi, jq, xdg-open
|
|
# Installed from ~/Development/hotkeys/ (cloned in stage 06).
|
|
info "Setting up hotkey scripts..."
|
|
HOTKEYS_DIR="$HOME/Development/hotkeys"
|
|
|
|
if [ -d "$HOTKEYS_DIR" ]; then
|
|
# Create a symlink or copy to ~/.local/bin for PATH access
|
|
for script in google.sh scholar.sh dictionary.sh pdf.sh emoji.sh hotstrings.sh; do
|
|
if [ -f "$HOTKEYS_DIR/$script" ]; then
|
|
ln -sf "$HOTKEYS_DIR/$script" "$HOME/.local/bin/${script%.sh}" 2>/dev/null || true
|
|
fi
|
|
done
|
|
ok "Hotkey scripts linked to ~/.local/bin/"
|
|
else
|
|
warn "hotkeys repo not cloned yet. Run stage 06 first."
|
|
fi
|
|
|
|
# ===========================================================================
|
|
# 2. Desktop Environment Keybindings
|
|
# ===========================================================================
|
|
# Map Julian's COSMIC keybindings to the current DE.
|
|
|
|
case "$DE" in
|
|
*GNOME*|*gnome*)
|
|
info "Configuring GNOME keybindings..."
|
|
|
|
# ---- Custom keybindings (hotkey scripts) ----
|
|
# Map Ctrl+Alt+{G,S,D,E,A,O} to the hotkey scripts
|
|
gsettings set org.gnome.settings-daemon.plugins.media-keys custom-keybindings "[]"
|
|
|
|
_add_gnome_kb() {
|
|
local name="$1"
|
|
local binding="$2"
|
|
local command="$3"
|
|
local path="/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/${name}/"
|
|
|
|
gsettings set org.gnome.settings-daemon.plugins.media-keys.custom-keybinding:"${path}" \
|
|
name "${name}" 2>/dev/null || true
|
|
gsettings set org.gnome.settings-daemon.plugins.media-keys.custom-keybinding:"${path}" \
|
|
binding "${binding}" 2>/dev/null || true
|
|
gsettings set org.gnome.settings-daemon.plugins.media-keys.custom-keybinding:"${path}" \
|
|
command "${command}" 2>/dev/null || true
|
|
}
|
|
|
|
_add_gnome_kb "google" "<Control><Alt>g" "$HOME/.local/bin/google"
|
|
_add_gnome_kb "scholar" "<Control><Alt>s" "$HOME/.local/bin/scholar"
|
|
_add_gnome_kb "dictionary" "<Control><Alt>d" "$HOME/.local/bin/dictionary"
|
|
_add_gnome_kb "emoji" "<Control><Alt>e" "$HOME/.local/bin/emoji"
|
|
_add_gnome_kb "hotstrings" "<Control><Alt>a" "$HOME/.local/bin/hotstrings"
|
|
_add_gnome_kb "pdf" "<Control><Alt>o" "$HOME/.local/bin/pdf"
|
|
|
|
# ---- Collect all custom paths into array for gsettings ----
|
|
KB_PATHS="["
|
|
for n in google scholar dictionary emoji hotstrings pdf; do
|
|
KB_PATHS+="'/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/${n}/', "
|
|
done
|
|
KB_PATHS="${KB_PATHS%, }]"
|
|
gsettings set org.gnome.settings-daemon.plugins.media-keys custom-keybindings "${KB_PATHS}"
|
|
|
|
# ---- GNOME-specific shortcuts ----
|
|
# Super+L → lock (default on GNOME too)
|
|
# Super+Q → close window (default is Alt+F4; set Super+Q too)
|
|
gsettings set org.gnome.desktop.wm.keybindings close "['<Super>q', '<Alt>F4']" 2>/dev/null || true
|
|
|
|
ok "GNOME keybindings configured."
|
|
;;
|
|
|
|
*COSMIC*)
|
|
info "Configuring COSMIC keybindings..."
|
|
# On COSMIC, keybindings are stored in:
|
|
# ~/.config/cosmic/com.system76.CosmicSettings.Shortcuts/v1/custom
|
|
# This is a RON (Rust Object Notation) file.
|
|
# We deploy our custom bindings from the config template.
|
|
if [ -f "$CONFIG_DIR/cosmic/custom-shortcuts.ron" ]; then
|
|
mkdir -p "$HOME/.config/cosmic/com.system76.CosmicSettings.Shortcuts/v1"
|
|
cp "$CONFIG_DIR/cosmic/custom-shortcuts.ron" \
|
|
"$HOME/.config/cosmic/com.system76.CosmicSettings.Shortcuts/v1/custom"
|
|
# Set terminal command (COSMIC desktop)
|
|
mkdir -p "$HOME/.config/cosmic/com.system76.CosmicSettings.Shortcuts/v1"
|
|
echo '{
|
|
Terminal: "/usr/bin/ghostty --gtk-single-instance=true",
|
|
}' > "$HOME/.config/cosmic/com.system76.CosmicSettings.Shortcuts/v1/system_actions"
|
|
ok "COSMIC keybindings deployed."
|
|
else
|
|
warn "COSMIC shortcuts template not found. Run 'cp config/cosmic/* ~/.config/cosmic/' manually."
|
|
fi
|
|
;;
|
|
|
|
*Hyprland*|*sway*|*Sway*)
|
|
info "Configuring Wayland compositor keybindings..."
|
|
warn "No automatic config for ${DE}. Apply manually from config/hotkeys/hyprland.conf or config/hotkeys/sway.config"
|
|
warn "See hotkeys/README.md for config examples."
|
|
;;
|
|
|
|
*KDE*|*Plasma*)
|
|
info "KDE Plasma detected. Applying keybindings via kwriteconfig..."
|
|
warn "KDE keybinding automation not yet implemented. Configure manually via System Settings > Shortcuts."
|
|
;;
|
|
|
|
*)
|
|
warn "Unknown DE: ${DE}. Keybindings must be configured manually."
|
|
warn "Reference: Ctrl+Alt+G/S/D/E/A/O → hotkey scripts in ~/Development/hotkeys/"
|
|
;;
|
|
esac
|
|
|
|
# ===========================================================================
|
|
# 4. Ghostty terminal config
|
|
# ===========================================================================
|
|
info "Deploying Ghostty config..."
|
|
mkdir -p "$HOME/.config/ghostty"
|
|
if [ -f "$CONFIG_DIR/ghostty/config" ]; then
|
|
cp "$CONFIG_DIR/ghostty/config" "$HOME/.config/ghostty/config"
|
|
ok "Ghostty config deployed."
|
|
fi
|
|
|
|
# ===========================================================================
|
|
# 5. Fonts (Nerd Fonts for terminal + dev)
|
|
# ===========================================================================
|
|
info "Installing Nerd Fonts..."
|
|
FONT_DIR="$HOME/.local/share/fonts"
|
|
mkdir -p "$FONT_DIR"
|
|
|
|
# MesloLGS NF — recommended for Powerlevel10k
|
|
# This is the font used on the Pop machine (MesloLGS NF Regular).
|
|
install_nerd_font() {
|
|
local font_name="$1"
|
|
local repo_url="$2"
|
|
local font_dir="$FONT_DIR"
|
|
|
|
# Check if already installed
|
|
if ls "$font_dir"/*"$font_name"* 2>/dev/null | grep -q .; then
|
|
ok "Font '$font_name' already installed."
|
|
return
|
|
fi
|
|
|
|
info "Downloading $font_name Nerd Font..."
|
|
local tmpdir
|
|
tmpdir=$(mktemp -d)
|
|
# Download from Nerd Fonts GitHub releases
|
|
curl -fsSL "https://github.com/ryanoasis/nerd-fonts/releases/latest/download/${font_name}.zip" \
|
|
-o "$tmpdir/${font_name}.zip" 2>/dev/null && {
|
|
unzip -o "$tmpdir/${font_name}.zip" -d "$tmpdir" 2>/dev/null
|
|
cp "$tmpdir"/*.ttf "$font_dir"/ 2>/dev/null || true
|
|
ok "Font '$font_name' installed."
|
|
} || warn "Font download failed for $font_name."
|
|
rm -rf "$tmpdir"
|
|
}
|
|
|
|
# On Pop, these were found:
|
|
# MesloLGS NF (Regular, Bold, Italic, Bold Italic)
|
|
# FiraCode Nerd Font Propo
|
|
# ApercuMonoPro-Regular.otf (proprietary — not distributed)
|
|
install_nerd_font "Meslo" ""
|
|
install_nerd_font "FiraCode" ""
|
|
|
|
# Rebuild font cache
|
|
fc-cache -f "$FONT_DIR" 2>/dev/null || true
|
|
ok "Font cache rebuilt."
|
|
|
|
# ===========================================================================
|
|
# 6. GTK Theme (dark mode + Papirus icons)
|
|
# ===========================================================================
|
|
info "Setting GTK theme and icons..."
|
|
gsettings set org.gnome.desktop.interface color-scheme 'prefer-dark' 2>/dev/null || true
|
|
gsettings set org.gnome.desktop.interface gtk-theme 'adw-gtk3-dark' 2>/dev/null || true
|
|
gsettings set org.gnome.desktop.interface icon-theme 'Papirus-Dark' 2>/dev/null || true
|
|
ok "GTK dark theme + Papirus icons set."
|
|
|
|
# ===========================================================================
|
|
# 7. Solaar (Logitech peripherals) config
|
|
# ===========================================================================
|
|
# The Pop machine had config for MX Keys Mini + MX Master 3.
|
|
# Solaar config is auto-generated when you pair devices. The config
|
|
# template (if supplied) can be placed at ~/.config/solaar/config.yaml
|
|
info "Solaar config will be generated automatically when you pair devices."
|
|
|
|
ok "Stage 09 complete: desktop configured."
|