| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252 |
- #!/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"
- }
|