#!/usr/bin/env bash # Script Standards and Common Functions # Source this file in your scripts for consistent behavior # ============================================================================== # STANDARD SCRIPT HEADER # ============================================================================== # All scripts should start with: # #!/usr/bin/env bash # # NAME: Brief description of what the script does # # REQUIRES: sudo interactive (if needed) # # set -euo pipefail # # # Source common functions (adjust path as needed) # source "$(dirname "$0")/common.sh" 2>/dev/null || true # ============================================================================== # CONFIGURATION # ============================================================================== readonly SCRIPT_NAME="${0##*/}" readonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" # Colors for output (only if terminal supports it) if [[ -t 1 ]] && command -v tput >/dev/null 2>&1; then readonly RED=$(tput setaf 1) readonly GREEN=$(tput setaf 2) readonly YELLOW=$(tput setaf 3) readonly BLUE=$(tput setaf 4) readonly PURPLE=$(tput setaf 5) readonly CYAN=$(tput setaf 6) readonly WHITE=$(tput setaf 7) readonly BOLD=$(tput bold) readonly RESET=$(tput sgr0) else readonly RED="" GREEN="" YELLOW="" BLUE="" PURPLE="" CYAN="" WHITE="" BOLD="" RESET="" fi # ============================================================================== # LOGGING FUNCTIONS # ============================================================================== log_info() { printf "${GREEN}[INFO]${RESET} %s\n" "$*" } log_warn() { printf "${YELLOW}[WARN]${RESET} %s\n" "$*" >&2 } log_error() { printf "${RED}[ERROR]${RESET} %s\n" "$*" >&2 } log_success() { printf "${GREEN}[SUCCESS]${RESET} %s\n" "$*" } log_debug() { if [[ "${DEBUG:-0}" == "1" ]]; then printf "${CYAN}[DEBUG]${RESET} %s\n" "$*" >&2 fi } log_sudo() { printf "${PURPLE}[SUDO]${RESET} %s\n" "$*" } # ============================================================================== # UTILITY FUNCTIONS # ============================================================================== command_exists() { command -v "$1" >/dev/null 2>&1 } is_root() { [[ $EUID -eq 0 ]] } require_root() { if ! is_root; then log_error "This script requires root privileges" log_info "Run with: sudo $0 $*" exit 1 fi } # Check if running in interactive terminal is_interactive() { [[ -t 0 && -t 1 ]] } # ============================================================================== # CONFIRMATION FUNCTIONS # ============================================================================== confirm() { local prompt="${1:-Continue?}" local default="${2:-n}" local response if ! is_interactive; then log_warn "Non-interactive mode, using default: $default" [[ "$default" == "y" ]] return $? fi while true; do if [[ "$default" == "y" ]]; then printf "%s [Y/n]: " "$prompt" else printf "%s [y/N]: " "$prompt" fi read -r response response=${response,,} # Convert to lowercase case "$response" in "") [[ "$default" == "y" ]] return $? ;; y | yes) return 0 ;; n | no) return 1 ;; *) log_warn "Please answer 'y' or 'n'" ;; esac done } # Show changes and confirm confirm_change() { local file="$1" local description="$2" local temp_file="$3" log_info "Proposed changes for $description:" log_info "File: $file" echo if command_exists colordiff; then colordiff -u "$file" "$temp_file" 2>/dev/null || diff -u "$file" "$temp_file" 2>/dev/null || true else diff -u "$file" "$temp_file" 2>/dev/null || true fi echo confirm "Apply these changes?" } # ============================================================================== # FILE OPERATIONS # ============================================================================== backup_file() { local file="$1" local backup_suffix="${2:-$(date +%Y%m%d_%H%M%S)}" local backup_file="${file}.backup.${backup_suffix}" if [[ -f "$file" ]]; then cp "$file" "$backup_file" log_info "Created backup: $backup_file" echo "$backup_file" fi } create_temp_file() { local template="${1:-tmp.XXXXXX}" mktemp "/tmp/${template}" } # ============================================================================== # PACKAGE MANAGEMENT # ============================================================================== install_packages() { local packages=("$@") if [[ ${#packages[@]} -eq 0 ]]; then log_warn "No packages specified" return 1 fi log_info "Installing packages: ${packages[*]}" if command_exists paru; then paru -S --needed --noconfirm "${packages[@]}" elif command_exists pacman; then sudo pacman -S --needed --noconfirm "${packages[@]}" else log_error "No supported package manager found" return 1 fi } # ============================================================================== # SERVICE MANAGEMENT # ============================================================================== enable_service() { local service="$1" local user_service="${2:-false}" if [[ "$user_service" == "true" ]]; then log_info "Enabling user service: $service" systemctl --user enable --now "$service" else log_info "Enabling system service: $service" sudo systemctl enable --now "$service" fi } # ============================================================================== # ERROR HANDLING # ============================================================================== cleanup() { local exit_code=$? # Add any cleanup operations here exit $exit_code } # Set up trap for cleanup trap cleanup EXIT INT TERM # ============================================================================== # SCRIPT INITIALIZATION # ============================================================================== init_script() { log_info "Starting $SCRIPT_NAME" # Set DEBUG mode if requested if [[ "${1:-}" == "--debug" ]]; then export DEBUG=1 log_debug "Debug mode enabled" shift fi } # ============================================================================== # SCRIPT COMPLETION # ============================================================================== finish_script() { local exit_code="${1:-0}" if [[ "$exit_code" -eq 0 ]]; then log_success "$SCRIPT_NAME completed successfully" else log_error "$SCRIPT_NAME failed with exit code $exit_code" fi exit "$exit_code" }