Created
June 1, 2026 19:31
-
-
Save dosjota/93cd666961e63b5d0b778b0508a81da8 to your computer and use it in GitHub Desktop.
configuracion para terminal
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| # ================================================================ | |
| # SETUP terminal: zsh + Oh My Zsh + Spaceship | |
| # | |
| # USO: | |
| # bash setup.sh → instalación completa | |
| # bash setup.sh --plugins → solo reinstalar plugins externos | |
| # bash setup.sh --config → solo regenerar configs (zshrc + spaceship) | |
| # bash setup.sh --update → actualizar plugins + spaceship (git pull) | |
| # | |
| # COMPATIBLE CON: macOS (Homebrew) · Ubuntu/Debian (apt) · Fedora/RHEL/CentOS (dnf/yum) | |
| # ================================================================ | |
| set -euo pipefail | |
| # ── Colores ─────────────────────────────────────────────────── | |
| RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m' | |
| BLUE='\033[0;34m'; CYAN='\033[0;36m'; BOLD='\033[1m'; NC='\033[0m' | |
| log() { echo -e "${CYAN}[SETUP]${NC} $*"; } | |
| ok() { echo -e "${GREEN}[ OK ]${NC} $*"; } | |
| warn() { echo -e "${YELLOW}[ WARN ]${NC} $*"; } | |
| error() { echo -e "${RED}[ERROR ]${NC} $*"; } | |
| section() { | |
| echo -e "\n${BLUE}${BOLD}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" | |
| echo -e "${BLUE}${BOLD} $*${NC}" | |
| echo -e "${BLUE}${BOLD}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" | |
| } | |
| # ── Rutas globales ──────────────────────────────────────────── | |
| ZSHRC="$HOME/.zshrc" | |
| ZSH_DIR="$HOME/.oh-my-zsh" | |
| ZSH_CUSTOM="${ZSH_CUSTOM:-$ZSH_DIR/custom}" | |
| SPACESHIP_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/spaceship" | |
| BACKUP_SUFFIX=".backup.$(date +%Y%m%d_%H%M%S)" | |
| OS="$(uname -s)" | |
| # ── URL del Gist — personalizar antes de publicar ──────────── | |
| # Uso: GIST_RAW_URL="https://..." bash setup.sh | |
| # o edita directamente esta línea con tu URL de Gist | |
| GIST_RAW_URL="${GIST_RAW_URL:-https://gist.github.com/dosjota/93cd666961e63b5d0b778b0508a81da8/raw}" | |
| EDITOR="${EDITOR:-vim}" | |
| # ── Detección de OS y gestor de paquetes ────────────────────── | |
| detect_os() { | |
| case "$(uname -s)" in | |
| Darwin) echo "macos" ;; | |
| Linux) | |
| if command -v apt-get &>/dev/null; then echo "debian" | |
| elif command -v dnf &>/dev/null; then echo "fedora" | |
| elif command -v yum &>/dev/null; then echo "rhel" | |
| else echo "linux-unknown"; fi ;; | |
| *) echo "unknown" ;; | |
| esac | |
| } | |
| OS_TYPE="$(detect_os)" | |
| # Instala paquetes con el gestor correcto para el OS actual | |
| pkg_install() { | |
| case "$OS_TYPE" in | |
| macos) brew install "$@" 2>/dev/null || true ;; | |
| debian) sudo apt-get install -y "$@" 2>/dev/null || true ;; | |
| fedora) sudo dnf install -y "$@" 2>/dev/null || true ;; | |
| rhel) sudo yum install -y "$@" 2>/dev/null || true ;; | |
| linux-unknown) warn "Instala manualmente: $*" ;; | |
| *) warn "OS no reconocido. Instala manualmente: $*" ;; | |
| esac | |
| } | |
| # ── Flags de modo ───────────────────────────────────────────── | |
| MODE_PLUGINS=false | |
| MODE_CONFIG=false | |
| MODE_UPDATE=false | |
| MODE_FULL=true | |
| for arg in "$@"; do | |
| case "$arg" in | |
| --plugins) MODE_PLUGINS=true; MODE_FULL=false ;; | |
| --config) MODE_CONFIG=true; MODE_FULL=false ;; | |
| --update) MODE_UPDATE=true; MODE_FULL=false ;; | |
| esac | |
| done | |
| # ================================================================ | |
| # FUNCIÓN: Instalar / actualizar plugin de Oh My Zsh | |
| # Uso: install_plugin <nombre> <url-git> | |
| # ================================================================ | |
| install_plugin() { | |
| local name="$1" | |
| local url="$2" | |
| local dir="$ZSH_CUSTOM/plugins/$name" | |
| if [[ -d "$dir/.git" ]]; then | |
| if [[ "$MODE_UPDATE" == true || "$MODE_FULL" == true ]]; then | |
| log "Actualizando $name..." | |
| git -C "$dir" pull --quiet --ff-only 2>/dev/null \ | |
| && ok "$name actualizado" \ | |
| || warn "$name — sin cambios o conflicto, saltando" | |
| else | |
| ok "$name ya instalado" | |
| fi | |
| else | |
| log "Instalando plugin: $name" | |
| if git clone --depth=1 "$url" "$dir" 2>/dev/null; then | |
| ok "$name instalado correctamente" | |
| else | |
| error "No se pudo instalar $name — verifica tu conexión a internet" | |
| fi | |
| fi | |
| } | |
| # ================================================================ | |
| # FUNCIÓN: Verificar que el plugin existe en disco | |
| # ================================================================ | |
| verify_plugin() { | |
| local name="$1" | |
| local dir="$ZSH_CUSTOM/plugins/$name" | |
| if [[ -d "$dir" ]]; then | |
| echo -e " ${GREEN}✓${NC} $name" | |
| else | |
| echo -e " ${RED}✗${NC} $name ${RED}← FALTA (corre: bash setup.sh --plugins)${NC}" | |
| fi | |
| } | |
| # ================================================================ | |
| # BLOQUE 1: DEPENDENCIAS DEL SISTEMA | |
| # ================================================================ | |
| if [[ "$MODE_FULL" == true ]]; then | |
| section "1/6 — Dependencias del sistema" | |
| case "$OS_TYPE" in | |
| macos) | |
| if ! command -v brew &>/dev/null; then | |
| error "Homebrew no encontrado. Instálalo primero: https://brew.sh" | |
| exit 1 | |
| fi | |
| log "macOS detectado — usando Homebrew" | |
| pkg_install zsh git curl zoxide fzf bat tmux gh jq git-delta direnv | |
| ;; | |
| debian) | |
| log "Linux (Debian/Ubuntu) detectado — usando apt-get" | |
| sudo apt-get update -qq 2>/dev/null | |
| pkg_install zsh git curl fzf tmux jq direnv | |
| # bat: en Debian/Ubuntu se llama batcat → crear symlink | |
| if ! command -v bat &>/dev/null; then | |
| pkg_install bat 2>/dev/null || true | |
| if command -v batcat &>/dev/null; then | |
| mkdir -p ~/.local/bin | |
| ln -sf "$(which batcat)" ~/.local/bin/bat | |
| ok "bat → symlink a batcat creado en ~/.local/bin/bat" | |
| fi | |
| fi | |
| if ! command -v zoxide &>/dev/null; then | |
| log "Instalando zoxide..." | |
| curl -sS https://raw.githubusercontent.com/ajeetdsouza/zoxide/main/install.sh | bash \ | |
| || warn "zoxide no pudo instalarse (opcional)" | |
| fi | |
| ;; | |
| fedora|rhel) | |
| local _pm; _pm=$(command -v dnf 2>/dev/null || command -v yum) | |
| log "Linux (Fedora/RHEL/CentOS) detectado — usando $_pm" | |
| sudo "$_pm" install -y epel-release 2>/dev/null || true | |
| pkg_install zsh git curl fzf tmux jq bat | |
| # Paquetes no disponibles en repos base → aviso con URL oficial | |
| warn "gh CLI: https://cli.github.com/manual/installation" | |
| warn "direnv: https://direnv.net/docs/installation.html" | |
| warn "git-delta: cargo install git-delta" | |
| if ! command -v zoxide &>/dev/null; then | |
| log "Instalando zoxide..." | |
| curl -sS https://raw.githubusercontent.com/ajeetdsouza/zoxide/main/install.sh | bash \ | |
| || warn "zoxide no pudo instalarse (opcional)" | |
| fi | |
| ;; | |
| *) | |
| warn "Sistema '$OS_TYPE' no reconocido — instala dependencias manualmente" | |
| ;; | |
| esac | |
| ok "Dependencias del sistema listas" | |
| fi | |
| # ================================================================ | |
| # BLOQUE 2: OH MY ZSH | |
| # Usamos RUNZSH=no CHSH=no para que el instalador NO ejecute | |
| # `exec zsh` al final, lo que cortaría nuestro script. | |
| # ================================================================ | |
| if [[ "$MODE_FULL" == true ]]; then | |
| section "2/6 — Oh My Zsh" | |
| if [[ -d "$ZSH_DIR" ]]; then | |
| warn "Oh My Zsh ya está instalado en $ZSH_DIR — saltando" | |
| else | |
| log "Instalando Oh My Zsh (modo silencioso, sin cambiar shell)..." | |
| RUNZSH=no CHSH=no \ | |
| sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" \ | |
| "" --unattended | |
| ok "Oh My Zsh instalado" | |
| fi | |
| # Re-exportar ZSH_CUSTOM ahora que OMZ existe en disco | |
| ZSH_CUSTOM="${ZSH_CUSTOM:-$ZSH_DIR/custom}" | |
| mkdir -p "$ZSH_CUSTOM/plugins" "$ZSH_CUSTOM/themes" | |
| fi | |
| # ================================================================ | |
| # BLOQUE 3: PLUGINS EXTERNOS | |
| # Estos NO vienen incluidos con Oh My Zsh y deben clonarse. | |
| # Sin este paso OMZ muestra "[oh-my-zsh] plugin 'X' not found" | |
| # ================================================================ | |
| if [[ "$MODE_FULL" == true || "$MODE_PLUGINS" == true || "$MODE_UPDATE" == true ]]; then | |
| section "3/6 — Plugins externos" | |
| # Asegurarse de que ZSH_CUSTOM existe aunque se corra en modo --plugins | |
| mkdir -p "$ZSH_CUSTOM/plugins" | |
| install_plugin "zsh-autosuggestions" "https://github.com/zsh-users/zsh-autosuggestions" | |
| install_plugin "zsh-syntax-highlighting" "https://github.com/zsh-users/zsh-syntax-highlighting" | |
| install_plugin "zsh-completions" "https://github.com/zsh-users/zsh-completions" | |
| install_plugin "zsh-history-substring-search" "https://github.com/zsh-users/zsh-history-substring-search" | |
| install_plugin "you-should-use" "https://github.com/MichaelAquilina/zsh-you-should-use" | |
| echo "" | |
| log "Verificando plugins externos:" | |
| verify_plugin "zsh-autosuggestions" | |
| verify_plugin "zsh-syntax-highlighting" | |
| verify_plugin "zsh-completions" | |
| verify_plugin "zsh-history-substring-search" | |
| verify_plugin "you-should-use" | |
| echo "" | |
| log "Plugins nativos de Oh My Zsh (sin instalación requerida):" | |
| for p in git gitignore z sudo extract fzf node npm yarn python pip \ | |
| rust docker docker-compose colored-man-pages \ | |
| command-not-found web-search jsontools urltools copypath copyfile; do | |
| if [[ -d "$ZSH_DIR/plugins/$p" ]]; then | |
| echo -e " ${GREEN}✓${NC} $p" | |
| else | |
| echo -e " ${YELLOW}~${NC} $p (no disponible en esta versión de OMZ)" | |
| fi | |
| done | |
| ok "Sección de plugins completada" | |
| fi | |
| # ================================================================ | |
| # BLOQUE 4: SPACESHIP v4 | |
| # ================================================================ | |
| if [[ "$MODE_FULL" == true || "$MODE_UPDATE" == true ]]; then | |
| section "4/6 — Spaceship Prompt v4" | |
| mkdir -p "$ZSH_CUSTOM/themes" | |
| SPACESHIP_CLONE_DIR="$ZSH_CUSTOM/themes/spaceship-prompt" | |
| SPACESHIP_THEME_LINK="$ZSH_CUSTOM/themes/spaceship.zsh-theme" | |
| if [[ -d "$SPACESHIP_CLONE_DIR/.git" ]]; then | |
| log "Actualizando Spaceship..." | |
| git -C "$SPACESHIP_CLONE_DIR" pull --quiet --ff-only 2>/dev/null \ | |
| && ok "Spaceship actualizado" \ | |
| || warn "Sin cambios en Spaceship" | |
| else | |
| log "Clonando Spaceship..." | |
| git clone --depth=1 https://github.com/spaceship-prompt/spaceship-prompt.git "$SPACESHIP_CLONE_DIR" | |
| ok "Spaceship clonado" | |
| fi | |
| # Symlink necesario para que OMZ encuentre el tema por nombre | |
| if [[ ! -L "$SPACESHIP_THEME_LINK" ]]; then | |
| ln -sf "$SPACESHIP_CLONE_DIR/spaceship.zsh-theme" "$SPACESHIP_THEME_LINK" | |
| ok "Symlink del tema creado" | |
| fi | |
| ok "Spaceship listo" | |
| fi | |
| # ================================================================ | |
| # BLOQUE 5: CONFIGURACIÓN DE SPACESHIP | |
| # Archivo: ~/.config/spaceship/spaceship.zsh | |
| # Se carga desde .zshrc. Editar aquí para personalizar el prompt. | |
| # ================================================================ | |
| if [[ "$MODE_FULL" == true || "$MODE_CONFIG" == true ]]; then | |
| section "5/6 — Configuración Spaceship" | |
| mkdir -p "$SPACESHIP_DIR" | |
| if [[ -f "$SPACESHIP_DIR/spaceship.zsh" ]]; then | |
| cp "$SPACESHIP_DIR/spaceship.zsh" "$SPACESHIP_DIR/spaceship.zsh${BACKUP_SUFFIX}" | |
| warn "Backup: $SPACESHIP_DIR/spaceship.zsh${BACKUP_SUFFIX}" | |
| fi | |
| cat > "$SPACESHIP_DIR/spaceship.zsh" << 'SPACESHIP_CONFIG' | |
| # ═══════════════════════════════════════════════════════════════ | |
| # SPACESHIP PROMPT — Configuración Profesional | |
| # Optimizado para: Flutter/Dart, Node, Rust, Python, Docker | |
| # | |
| # Para editar: spaceshipconfig (alias definido en .zshrc) | |
| # Docs: https://spaceship-prompt.sh/config/intro/ | |
| # ═══════════════════════════════════════════════════════════════ | |
| # ── ORDEN DEL PROMPT (línea superior) ──────────────────────── | |
| SPACESHIP_PROMPT_ORDER=( | |
| time # ⏰ Hora (desactivado por defecto) | |
| user # 👤 Usuario (solo si root o SSH) | |
| host # 🖥 Host (solo si SSH) | |
| dir # 📁 Directorio actual | |
| git # 🌿 Rama + estado git | |
| package # 📦 Versión del paquete del proyecto | |
| node # ⬢ Node.js | |
| bun # 🍞 Bun | |
| deno # 🦕 Deno | |
| python # 🐍 Python (con virtualenv) | |
| rust # 🦀 Rust | |
| dart # 🎯 Dart / Flutter | |
| golang # 🐹 Go | |
| docker # 🐳 Docker context | |
| aws # ☁️ AWS profile (activa con: profile use aws) | |
| exec_time # ⏱ Tiempo de ejecución (si > umbral) | |
| async # ⟳ Indicador de carga async | |
| line_sep # ↵ Salto de línea → comando en línea 2 | |
| jobs # ⚙ Jobs en background | |
| exit_code # ✘ Código de error (si ≠ 0) | |
| char # ❯ Carácter del prompt | |
| ) | |
| # ── PROMPT DERECHO ──────────────────────────────────────────── | |
| SPACESHIP_RPROMPT_ORDER=(cloud_profile) # Perfil de nube activo (ver ~/.zsh/active_profile) | |
| # ── COMPORTAMIENTO GENERAL ──────────────────────────────────── | |
| SPACESHIP_PROMPT_ADD_NEWLINE=true # Línea en blanco antes del prompt | |
| SPACESHIP_PROMPT_SEPARATE_LINE=true # Comando en su propia línea | |
| SPACESHIP_PROMPT_FIRST_PREFIX_SHOW=false | |
| SPACESHIP_PROMPT_ASYNC=true # No bloquea mientras carga git/versiones | |
| # ═══════════════════════════════════════════════════════════════ | |
| # SECCIONES — ajustar SHOW=true/false para activar/desactivar | |
| # ═══════════════════════════════════════════════════════════════ | |
| # ── TIEMPO ──────────────────────────────────────────────────── | |
| SPACESHIP_TIME_SHOW=false # true para ver la hora en el prompt | |
| SPACESHIP_TIME_FORMAT="%T" | |
| SPACESHIP_TIME_COLOR="yellow" | |
| # ── USUARIO / HOST ──────────────────────────────────────────── | |
| SPACESHIP_USER_SHOW="needed" # Solo si root o SSH | |
| SPACESHIP_USER_COLOR="yellow" | |
| SPACESHIP_USER_COLOR_ROOT="red" | |
| SPACESHIP_HOST_SHOW="needed" # Solo en SSH | |
| SPACESHIP_HOST_COLOR_SSH="cyan" | |
| # ── DIRECTORIO ──────────────────────────────────────────────── | |
| SPACESHIP_DIR_SHOW=true | |
| SPACESHIP_DIR_TRUNC=3 # Últimas 3 partes del path | |
| SPACESHIP_DIR_TRUNC_REPO=true # En repos git, trunca desde la raíz del repo | |
| SPACESHIP_DIR_COLOR="cyan" | |
| SPACESHIP_DIR_LOCK_SYMBOL=" " | |
| SPACESHIP_DIR_LOCK_COLOR="red" | |
| # ── GIT — RAMA ──────────────────────────────────────────────── | |
| SPACESHIP_GIT_SHOW=true | |
| SPACESHIP_GIT_PREFIX=" " | |
| SPACESHIP_GIT_SYMBOL=" " | |
| SPACESHIP_GIT_BRANCH_COLOR="magenta" | |
| # ── GIT — ESTADO ────────────────────────────────────────────── | |
| SPACESHIP_GIT_STATUS_SHOW=true | |
| SPACESHIP_GIT_STATUS_PREFIX=" [" | |
| SPACESHIP_GIT_STATUS_SUFFIX="]" | |
| SPACESHIP_GIT_STATUS_COLOR="red" | |
| SPACESHIP_GIT_STATUS_COLOR_GOOD="green" | |
| SPACESHIP_GIT_STATUS_UNTRACKED="?" # Sin rastrear | |
| SPACESHIP_GIT_STATUS_ADDED="+" # En staging | |
| SPACESHIP_GIT_STATUS_MODIFIED="!" # Modificados | |
| SPACESHIP_GIT_STATUS_RENAMED="»" # Renombrados | |
| SPACESHIP_GIT_STATUS_DELETED="✘" # Eliminados | |
| SPACESHIP_GIT_STATUS_STASHED="$" # Stash activo | |
| SPACESHIP_GIT_STATUS_UNMERGED="═" # Conflictos de merge | |
| SPACESHIP_GIT_STATUS_AHEAD="⇡" # Commits adelante del remoto | |
| SPACESHIP_GIT_STATUS_BEHIND="⇣" # Commits atrás del remoto | |
| SPACESHIP_GIT_STATUS_DIVERGED="⇕" # Divergido (ahead + behind) | |
| # ── PACKAGE ─────────────────────────────────────────────────── | |
| # Lee: package.json · Cargo.toml · pubspec.yaml · pyproject.toml | |
| SPACESHIP_PACKAGE_SHOW=true | |
| SPACESHIP_PACKAGE_PREFIX="is " | |
| SPACESHIP_PACKAGE_SYMBOL="📦 " | |
| SPACESHIP_PACKAGE_COLOR="yellow" | |
| # ── NODE.JS ─────────────────────────────────────────────────── | |
| SPACESHIP_NODE_SHOW=true | |
| SPACESHIP_NODE_SYMBOL="⬢ " | |
| SPACESHIP_NODE_COLOR="green" | |
| # ── BUN ─────────────────────────────────────────────────────── | |
| SPACESHIP_BUN_SHOW=true | |
| SPACESHIP_BUN_SYMBOL="🍞 " | |
| SPACESHIP_BUN_COLOR="yellow" | |
| # ── PYTHON ──────────────────────────────────────────────────── | |
| SPACESHIP_PYTHON_SHOW=true | |
| SPACESHIP_PYTHON_SYMBOL="🐍 " | |
| SPACESHIP_PYTHON_COLOR="yellow" | |
| # ── RUST ────────────────────────────────────────────────────── | |
| SPACESHIP_RUST_SHOW=true | |
| SPACESHIP_RUST_SYMBOL="🦀 " | |
| SPACESHIP_RUST_COLOR="red" | |
| # ── DART ────────────────────────────────────────────────────── | |
| SPACESHIP_DART_SHOW=true | |
| SPACESHIP_DART_SYMBOL="🎯 " | |
| SPACESHIP_DART_COLOR="blue" | |
| # ── GOLANG ──────────────────────────────────────────────────── | |
| SPACESHIP_GOLANG_SHOW=true | |
| SPACESHIP_GOLANG_SYMBOL="🐹 " | |
| SPACESHIP_GOLANG_COLOR="cyan" | |
| # ── DOCKER ──────────────────────────────────────────────────── | |
| SPACESHIP_DOCKER_SHOW=true | |
| SPACESHIP_DOCKER_SYMBOL="🐳 " | |
| SPACESHIP_DOCKER_COLOR="cyan" | |
| SPACESHIP_DOCKER_VERBOSE=false # Solo contexto, no versión del daemon | |
| # ── AWS ─────────────────────────────────────────────────────── | |
| SPACESHIP_AWS_SHOW=false | |
| SPACESHIP_AWS_SYMBOL="☁️ " | |
| SPACESHIP_AWS_COLOR="yellow" | |
| # ── TIEMPO DE EJECUCIÓN ─────────────────────────────────────── | |
| SPACESHIP_EXEC_TIME_SHOW=true | |
| SPACESHIP_EXEC_TIME_PREFIX="took " | |
| SPACESHIP_EXEC_TIME_COLOR="yellow" | |
| SPACESHIP_EXEC_TIME_ELAPSED=3 # Solo si el comando tardó > 3 segundos | |
| SPACESHIP_EXEC_TIME_PRECISION=1 | |
| # ── JOBS EN BACKGROUND ──────────────────────────────────────── | |
| SPACESHIP_JOBS_SHOW=true | |
| SPACESHIP_JOBS_SYMBOL="✦" | |
| SPACESHIP_JOBS_COLOR="blue" | |
| SPACESHIP_JOBS_AMOUNT_SHOW=true | |
| # ── CÓDIGO DE SALIDA ────────────────────────────────────────── | |
| SPACESHIP_EXIT_CODE_SHOW=true | |
| SPACESHIP_EXIT_CODE_SYMBOL="✘ " | |
| SPACESHIP_EXIT_CODE_COLOR="red" | |
| # ── CARÁCTER DEL PROMPT ─────────────────────────────────────── | |
| SPACESHIP_CHAR_SYMBOL="❯" | |
| SPACESHIP_CHAR_SYMBOL_ROOT="#" | |
| SPACESHIP_CHAR_SUFFIX=" " | |
| SPACESHIP_CHAR_SYMBOL_SECONDARY="…" | |
| SPACESHIP_CHAR_COLOR_SUCCESS="green" | |
| SPACESHIP_CHAR_COLOR_FAILURE="red" | |
| SPACESHIP_CHAR_COLOR_SECONDARY="yellow" | |
| # ── CLOUD PROFILE — sección custom del RPROMPT ──────────────── | |
| # Muestra el perfil activo con color por proveedor | |
| spaceship_cloud_profile() { | |
| local file="$HOME/.zsh/active_profile" | |
| [[ ! -f "$file" ]] && return | |
| local name; name=$(< "$file") | |
| [[ -z "$name" || "$name" == "default" ]] && return # default = local limpio, sin indicador | |
| local color | |
| case "$name" in | |
| *gcloud*|*gcp*) color="blue" ;; | |
| *aws*) color="yellow" ;; | |
| *firebase*) color="red" ;; | |
| *azure*) color="cyan" ;; | |
| *) color="magenta" ;; | |
| esac | |
| spaceship::section --color "$color" "[$name] " | |
| } | |
| SPACESHIP_CONFIG | |
| ok "Configuración de Spaceship creada en $SPACESHIP_DIR/spaceship.zsh" | |
| fi | |
| # ================================================================ | |
| # BLOQUE 6: .ZSHRC PRINCIPAL | |
| # ================================================================ | |
| if [[ "$MODE_FULL" == true || "$MODE_CONFIG" == true ]]; then | |
| section "6/6 — Archivo .zshrc" | |
| if [[ -f "$ZSHRC" ]]; then | |
| cp "$ZSHRC" "${ZSHRC}${BACKUP_SUFFIX}" | |
| warn "Backup guardado en ${ZSHRC}${BACKUP_SUFFIX}" | |
| fi | |
| cat > "$ZSHRC" << 'ZSHRC_CONTENT' | |
| # ═══════════════════════════════════════════════════════════════ | |
| # .ZSHRC — Configuración Profesional de Zsh | |
| # Stack: Oh My Zsh + Spaceship v4 + plugins esenciales | |
| # | |
| # Regenerar este archivo: bash ~/setup.sh --config | |
| # Actualizar plugins: bash ~/setup.sh --update | |
| # Reinstalar plugins: bash ~/setup.sh --plugins | |
| # | |
| # 💡 TIP: Crea un archivo ~/.zshrc.local para tus secretos, | |
| # tokens (AWS, GitHub) y configuraciones privadas. | |
| # ═══════════════════════════════════════════════════════════════ | |
| # ── URL del Gist (personalizar con tu URL real) ─────────────── | |
| GIST_RAW_URL="${GIST_RAW_URL:-__GIST_RAW_URL__}" | |
| # ── Compilar autocompletions solo si tienen más de 24h ──────── | |
| autoload -Uz compinit | |
| if [[ -n "${ZDOTDIR:-$HOME}/.zcompdump"(#qN.mh+24) ]]; then | |
| compinit | |
| else | |
| compinit -C | |
| fi | |
| # Compilar a bytecode para mayor velocidad | |
| if [[ -s "${ZDOTDIR:-$HOME}/.zcompdump" && (! -s "${ZDOTDIR:-$HOME}/.zcompdump.zwc" || "${ZDOTDIR:-$HOME}/.zcompdump" -nt "${ZDOTDIR:-$HOME}/.zcompdump.zwc") ]]; then | |
| zcompile "${ZDOTDIR:-$HOME}/.zcompdump" | |
| fi | |
| # ── OH MY ZSH ───────────────────────────────────────────────── | |
| export ZSH="$HOME/.oh-my-zsh" | |
| ZSH_THEME="spaceship" | |
| zstyle ':omz:update' mode auto | |
| zstyle ':omz:update' frequency 7 | |
| COMPLETION_WAITING_DOTS="true" | |
| HIST_STAMPS="yyyy-mm-dd" | |
| DISABLE_UNTRACKED_FILES_DIRTY="false" | |
| # ── PLUGINS ─────────────────────────────────────────────────── | |
| # [nativo] → viene incluido con Oh My Zsh, no requiere instalación | |
| # [externo] → clonado por setup.sh en ~/.oh-my-zsh/custom/plugins/ | |
| # Si faltan: bash ~/setup.sh --plugins | |
| plugins=( | |
| # Git [nativo] | |
| git | |
| gitignore | |
| # Terminal / UX [nativo] | |
| sudo # Esc+Esc añade sudo al comando anterior | |
| extract # x <archivo> descomprime cualquier formato | |
| copypath # Copia el path actual al clipboard | |
| copyfile # Copia el contenido de un archivo al clipboard | |
| colored-man-pages # Man pages con colores | |
| command-not-found # Sugiere paquetes al escribir comandos que no existen | |
| # Navegación [nativo] | |
| z # z <dir> para saltar a directorios frecuentes | |
| # Búsqueda [nativo] | |
| fzf # Ctrl+R historial, Ctrl+T archivos, Alt+C dirs | |
| # Lenguajes / Runtimes [nativo — solo activos si el binario existe] | |
| node | |
| npm | |
| yarn | |
| python | |
| pip | |
| rust | |
| docker | |
| docker-compose | |
| # Utilidades [nativo] | |
| web-search # google <query>, ddg <query> | |
| jsontools # pp_json, is_json, etc. | |
| urltools # urlencode / urldecode | |
| # ── Plugins EXTERNOS (requieren instalación con setup.sh) ─── | |
| zsh-autosuggestions # Sugerencias estilo fish → para aceptar | |
| zsh-syntax-highlighting # Syntax highlighting en tiempo real | |
| zsh-completions # Completions adicionales de la comunidad | |
| zsh-history-substring-search # ↑↓ busca en historial por substring | |
| you-should-use # Recuerda usar alias cuando puedes | |
| ) | |
| source "$ZSH/oh-my-zsh.sh" | |
| # ── SPACESHIP — cargar configuración desde archivo separado ─── | |
| SPACESHIP_CONFIG_FILE="${XDG_CONFIG_HOME:-$HOME/.config}/spaceship/spaceship.zsh" | |
| [[ -f "$SPACESHIP_CONFIG_FILE" ]] && source "$SPACESHIP_CONFIG_FILE" | |
| # ── fpath para zsh-completions ──────────────────────────────── | |
| fpath+="${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/plugins/zsh-completions/src" | |
| # ═══════════════════════════════════════════════════════════════ | |
| # ENTORNO & PATH | |
| # ═══════════════════════════════════════════════════════════════ | |
| export LANG="en_US.UTF-8" | |
| export LC_ALL="en_US.UTF-8" | |
| export EDITOR="${EDITOR:-vim}" | |
| export VISUAL="$EDITOR" | |
| export PATH="$HOME/.local/bin:$HOME/bin:$PATH" | |
| # ── Node (nvm) ──────────────────────────────────────────────── | |
| export NVM_DIR="$HOME/.nvm" | |
| [ -s "$NVM_DIR/nvm.sh" ] && source "$NVM_DIR/nvm.sh" --no-use | |
| [ -s "$NVM_DIR/bash_completion" ] && source "$NVM_DIR/bash_completion" | |
| # ── Rust / Cargo ────────────────────────────────────────────── | |
| [ -f "$HOME/.cargo/env" ] && source "$HOME/.cargo/env" | |
| # ── Python (pyenv) ──────────────────────────────────────────── | |
| if command -v pyenv &>/dev/null; then | |
| export PYENV_ROOT="$HOME/.pyenv" | |
| export PATH="$PYENV_ROOT/bin:$PATH" | |
| eval "$(pyenv init --path)" | |
| eval "$(pyenv init -)" | |
| fi | |
| # ── Flutter / Dart ──────────────────────────────────────────── | |
| for _flutter_path in \ | |
| "$HOME/flutter" \ | |
| "$HOME/development/flutter" \ | |
| "$HOME/snap/flutter/current" \ | |
| "/opt/flutter" \ | |
| "/usr/local/flutter"; do | |
| if [[ -d "$_flutter_path/bin" ]]; then | |
| export PATH="$_flutter_path/bin:$PATH" | |
| break | |
| fi | |
| done | |
| [[ -d "$HOME/.pub-cache/bin" ]] && export PATH="$HOME/.pub-cache/bin:$PATH" | |
| # ── Go ──────────────────────────────────────────────────────── | |
| if command -v go &>/dev/null; then | |
| export GOPATH="${GOPATH:-$HOME/go}" | |
| export PATH="$GOPATH/bin:$PATH" | |
| fi | |
| # ── Android ─────────────────────────────────────────────────── | |
| for _android_path in \ | |
| "$HOME/Library/Android/sdk" \ | |
| "$HOME/Android/Sdk" \ | |
| "$HOME/android-sdk" \ | |
| "/opt/android-sdk"; do | |
| if [[ -d "$_android_path" ]]; then | |
| export ANDROID_HOME="$_android_path" | |
| export PATH="$ANDROID_HOME/emulator:$ANDROID_HOME/tools:$ANDROID_HOME/tools/bin:$ANDROID_HOME/platform-tools:$PATH" | |
| break | |
| fi | |
| done | |
| # ── Zoxide (cd inteligente) ─────────────────────────────────── | |
| if command -v zoxide &>/dev/null; then | |
| eval "$(zoxide init zsh --cmd cd)" | |
| fi | |
| # ═══════════════════════════════════════════════════════════════ | |
| # HISTORIAL | |
| # ═══════════════════════════════════════════════════════════════ | |
| HISTSIZE=50000 | |
| SAVEHIST=50000 | |
| HISTFILE="$HOME/.zsh_history" | |
| setopt HIST_IGNORE_ALL_DUPS | |
| setopt HIST_IGNORE_SPACE | |
| setopt HIST_REDUCE_BLANKS | |
| setopt SHARE_HISTORY | |
| setopt EXTENDED_HISTORY | |
| # ── History substring search: buscar con ↑ ↓ ───────────────── | |
| bindkey '^[[A' history-substring-search-up | |
| bindkey '^[[B' history-substring-search-down | |
| # ═══════════════════════════════════════════════════════════════ | |
| # AUTOSUGGESTIONS | |
| # ═══════════════════════════════════════════════════════════════ | |
| ZSH_AUTOSUGGEST_STRATEGY=(history completion) | |
| ZSH_AUTOSUGGEST_BUFFER_MAX_SIZE=30 | |
| ZSH_AUTOSUGGEST_USE_ASYNC=true | |
| ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE="fg=#555555,underline" | |
| bindkey '→' autosuggest-accept # → acepta sugerencia completa | |
| bindkey '^[[1;5C' autosuggest-accept-word # Ctrl+→ acepta una palabra (macOS) | |
| bindkey '^[f' autosuggest-accept-word # Alt+f acepta una palabra (Linux) | |
| # ═══════════════════════════════════════════════════════════════ | |
| # FZF — Fuzzy Finder | |
| # ═══════════════════════════════════════════════════════════════ | |
| # (fzf keybindings son cargados automáticamente por el plugin de Oh My Zsh) | |
| export FZF_DEFAULT_OPTS=" | |
| --height=60% | |
| --layout=reverse | |
| --border=rounded | |
| --info=inline | |
| --color=bg+:#1e1e2e,bg:#1e1e2e,spinner:#f5c2e7,hl:#f38ba8 | |
| --color=fg:#cdd6f4,header:#f38ba8,info:#cba6f7,pointer:#f5c2e7 | |
| --color=marker:#f5c2e7,fg+:#cdd6f4,prompt:#cba6f7,hl+:#f38ba8 | |
| " | |
| export FZF_CTRL_R_OPTS="--preview 'echo {}' --preview-window=hidden" | |
| export FZF_ALT_C_OPTS="--preview 'ls -la --color=always {}'" | |
| if command -v fd &>/dev/null; then | |
| export FZF_DEFAULT_COMMAND='fd --type f --hidden --follow --exclude .git' | |
| export FZF_CTRL_T_COMMAND="$FZF_DEFAULT_COMMAND" | |
| fi | |
| # ═══════════════════════════════════════════════════════════════ | |
| # ALIASES | |
| # ═══════════════════════════════════════════════════════════════ | |
| # ── Archivos ────────────────────────────────────────────────── | |
| # ls: detectar GNU (Linux) vs BSD (macOS) para --color | |
| if ls --color=auto /dev/null &>/dev/null 2>&1; then | |
| alias ls='ls --color=auto' # GNU ls (Linux) | |
| else | |
| alias ls='ls -G' # BSD ls (macOS) | |
| fi | |
| alias ll='ls -lahF' | |
| alias la='ls -A' | |
| # ── Navegación ──────────────────────────────────────────────── | |
| alias ..='cd ..' | |
| alias ...='cd ../..' | |
| alias ....='cd ../../..' | |
| alias ~='cd ~' | |
| alias -- -='cd -' | |
| # ── Git ─────────────────────────────────────────────────────── | |
| alias g='git' | |
| alias gs='git status -sb' | |
| alias ga='git add' | |
| alias gaa='git add --all' | |
| alias gc='git commit -m' | |
| alias gca='git commit --amend --no-edit' | |
| alias gco='git checkout' | |
| alias gcb='git checkout -b' | |
| alias gd='git diff' | |
| alias gds='git diff --staged' | |
| alias gl='git log --oneline --graph --decorate --all' | |
| alias gll='git log --graph --pretty=format:"%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset" --abbrev-commit --all' | |
| alias gp='git push' | |
| alias gpf='git push --force-with-lease' | |
| alias gpl='git pull --rebase' | |
| alias gst='git stash' | |
| alias gstp='git stash pop' | |
| alias gstl='git stash list' | |
| alias gclean='git branch --merged | grep -v "main\|master\|develop\|HEAD" | xargs -r git branch -d' | |
| alias gwip='git add -A && git commit -m "wip: 🚧 work in progress"' | |
| alias gunwip='git reset HEAD~1 --soft' | |
| # ── Flutter / Dart ──────────────────────────────────────────── | |
| alias flr='flutter run' | |
| alias flb='flutter build' | |
| alias flc='flutter clean && flutter pub get' | |
| alias fltest='flutter test' | |
| alias flanalyze='flutter analyze' | |
| alias flfmt='dart format .' | |
| alias flpubget='flutter pub get' | |
| alias flupgrade='flutter pub upgrade' | |
| alias fldevices='flutter devices' | |
| alias fldoctor='flutter doctor -v' | |
| # ── Node / npm / yarn / bun ─────────────────────────────────── | |
| alias ni='npm install' | |
| alias nid='npm install --save-dev' | |
| alias nr='npm run' | |
| alias nrd='npm run dev' | |
| alias nrb='npm run build' | |
| alias nrt='npm run test' | |
| alias nrclean='rm -rf node_modules && npm install' | |
| alias yi='yarn install' | |
| alias yr='yarn run' | |
| alias bi='bun install' | |
| alias br='bun run' | |
| alias brd='bun run dev' | |
| # ── Rust / Cargo ────────────────────────────────────────────── | |
| alias cb='cargo build' | |
| alias cr='cargo run' | |
| alias ct='cargo test' | |
| alias cc='cargo check' | |
| alias cf='cargo fmt' | |
| alias ccl='cargo clippy' | |
| alias cw='cargo watch -x run' | |
| # ── Python ──────────────────────────────────────────────────── | |
| alias py='python3' | |
| alias pip='pip3' | |
| alias venv='python3 -m venv .venv' | |
| alias activate='source .venv/bin/activate' | |
| # ── Docker ──────────────────────────────────────────────────── | |
| alias d='docker' | |
| alias dc='docker compose' | |
| alias dcu='docker compose up -d' | |
| alias dcd='docker compose down' | |
| alias dcl='docker compose logs -f' | |
| alias dps='docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"' | |
| alias dclean='docker system prune -af --volumes' | |
| alias dsh='docker exec -it' | |
| alias dkillall='docker kill $(docker ps -q) 2>/dev/null || echo "No hay contenedores corriendo"' | |
| # ── Sistema ─────────────────────────────────────────────────── | |
| alias c='clear' | |
| alias q='exit' | |
| alias reload='exec zsh' | |
| alias zshconfig='$EDITOR ~/.zshrc' | |
| alias spaceshipconfig='$EDITOR ${XDG_CONFIG_HOME:-$HOME/.config}/spaceship/spaceship.zsh' | |
| alias update-terminal='bash <(curl -sL "$GIST_RAW_URL/setup.sh") --update' | |
| alias duf='du -sh * | sort -rh | head -20' | |
| alias ports='lsof -iTCP -sTCP:LISTEN -P -n' | |
| alias myip='curl -s ifconfig.me' | |
| alias localip='ipconfig getifaddr en0 2>/dev/null || hostname -I | awk "{print \$1}"' | |
| alias serve='python3 -m http.server 8080' | |
| alias json='python3 -m json.tool' | |
| # ── Editores ────────────────────────────────────────────────── | |
| alias agy="open -a 'Antigravity'" | |
| alias code="open -a 'Visual Studio Code'" | |
| if command -v bat &>/dev/null; then | |
| alias cat='bat --paging=never --style=plain' | |
| alias bcat='bat' | |
| fi | |
| # ═══════════════════════════════════════════════════════════════ | |
| # FUNCIONES | |
| # ═══════════════════════════════════════════════════════════════ | |
| # Crear directorio y entrar | |
| mkcd() { mkdir -p "$1" && cd "$1"; } | |
| # Clonar repo y entrar | |
| gclone() { git clone "$1" && cd "$(basename "$1" .git)"; } | |
| # Matar proceso por puerto | |
| killport() { | |
| local port="$1" | |
| local pids | |
| if command -v lsof &>/dev/null; then | |
| pids=$(lsof -t -i ":$port" 2>/dev/null) | |
| elif command -v ss &>/dev/null; then | |
| pids=$(ss -lptn "sport = :$port" 2>/dev/null | grep -oP 'pid=\K[0-9]+') | |
| fi | |
| if [[ -n "$pids" ]]; then | |
| echo "$pids" | xargs kill -9 | |
| echo "✓ Proceso(s) en puerto :$port terminado(s)" | |
| else | |
| echo "No hay proceso escuchando en el puerto :$port" | |
| fi | |
| } | |
| # Información completa del proyecto git actual | |
| project_info() { | |
| echo "" | |
| echo " 📁 Directorio : $(pwd)" | |
| if git rev-parse --is-inside-work-tree &>/dev/null 2>&1; then | |
| echo " 🌿 Rama : $(git branch --show-current)" | |
| echo " 📍 Remote : $(git remote get-url origin 2>/dev/null || echo 'sin remote')" | |
| echo " 🕒 Último : $(git log -1 --format='%cr — %s' 2>/dev/null)" | |
| echo " 📊 Estado :" | |
| git status -sb | sed 's/^/ /' | |
| else | |
| echo " ⚠️ No es un repositorio git" | |
| fi | |
| for f in "package.json" "Cargo.toml" "pubspec.yaml" "pyproject.toml" "go.mod"; do | |
| [[ -f "$f" ]] && echo " 📦 Package : $f detectado" && break | |
| done | |
| echo "" | |
| } | |
| alias pi='project_info' | |
| # Buscar en historial con fzf | |
| fh() { | |
| local cmd | |
| cmd=$(fc -rln 1 | fzf --no-sort --tac --query="$*" --prompt="historial > ") | |
| [[ -n "$cmd" ]] && eval "$cmd" | |
| } | |
| # Ver contenido de archivo comprimido sin extraerlo | |
| peek() { | |
| case "$1" in | |
| *.tar.gz|*.tgz) tar tzf "$1" ;; | |
| *.tar.bz2) tar tjf "$1" ;; | |
| *.zip) unzip -l "$1" ;; | |
| *.7z) 7z l "$1" ;; | |
| *) echo "Formato no reconocido: $1" ;; | |
| esac | |
| } | |
| # Generar llave SSH y copiar al portapapeles | |
| genssh() { | |
| local email="$1" | |
| if [[ -z "$email" ]]; then | |
| echo "Uso: genssh <tu_email@ejemplo.com>" | |
| return 1 | |
| fi | |
| ssh-keygen -t ed25519 -C "$email" -f ~/.ssh/id_ed25519 -q -N "" | |
| eval "$(ssh-agent -s)" >/dev/null | |
| ssh-add ~/.ssh/id_ed25519 | |
| if command -v pbcopy &>/dev/null; then | |
| pbcopy < ~/.ssh/id_ed25519.pub | |
| echo "✓ Llave SSH copiada al portapapeles (pbcopy)" | |
| elif command -v xclip &>/dev/null; then | |
| xclip -selection clipboard < ~/.ssh/id_ed25519.pub | |
| echo "✓ Llave SSH copiada al portapapeles (xclip)" | |
| else | |
| echo "✓ Tu llave pública es:" | |
| cat ~/.ssh/id_ed25519.pub | |
| fi | |
| } | |
| # Eliminar todos los node_modules recursivamente | |
| nukemodules() { | |
| echo "⚠️ Buscando y eliminando 'node_modules' desde $(pwd)..." | |
| find . -name "node_modules" -type d -prune -print -exec rm -rf '{}' + | |
| echo "✓ Limpieza completada." | |
| } | |
| # Auto-switch NVM | |
| autoload -U add-zsh-hook | |
| load-nvmrc() { | |
| local nvmrc_path="$(nvm_find_nvmrc 2>/dev/null)" | |
| if [ -n "$nvmrc_path" ]; then | |
| local nvmrc_node_version=$(nvm version "$(cat "${nvmrc_path}")" 2>/dev/null) | |
| if [ "$nvmrc_node_version" = "N/A" ]; then | |
| nvm install | |
| elif [ "$nvmrc_node_version" != "$(nvm version 2>/dev/null)" ]; then | |
| nvm use | |
| fi | |
| fi | |
| } | |
| add-zsh-hook chpwd load-nvmrc | |
| load-nvmrc 2>/dev/null | |
| # Hook de Direnv | |
| if command -v direnv &>/dev/null; then | |
| eval "$(direnv hook zsh)" | |
| fi | |
| # ═══════════════════════════════════════════════════════════════ | |
| # PERFILES DE ENTORNO (Cloud / Project) | |
| # profile list | use <n> | new <n> | edit [n] | show | off | |
| # ═══════════════════════════════════════════════════════════════ | |
| PROFILES_DIR="$HOME/.zsh/profiles" | |
| ACTIVE_PROFILE_FILE="$HOME/.zsh/active_profile" | |
| profile() { | |
| local cmd="${1:-list}" | |
| case "$cmd" in | |
| list) | |
| echo "" | |
| echo " Perfiles disponibles:" | |
| local active; active=$(cat "$ACTIVE_PROFILE_FILE" 2>/dev/null) | |
| for f in "$PROFILES_DIR"/*.zsh(N); do | |
| local name; name=$(basename "$f" .zsh) | |
| [[ "$name" == "$active" ]] && echo " \u2713 $name \u2190 activo" || echo " \u00b7 $name" | |
| done | |
| echo "" | |
| ;; | |
| use) | |
| local name="${2:-}" | |
| [[ -z "$name" ]] && echo "Uso: profile use <nombre>" && return 1 | |
| local file="$PROFILES_DIR/$name.zsh" | |
| [[ ! -f "$file" ]] && echo "✗ Perfil '$name' no encontrado. Usa: profile list" && return 1 | |
| echo "$name" > "$ACTIVE_PROFILE_FILE" | |
| # Limpiar metadatos previos | |
| unset PROFILE_DISPLAY_NAME PROFILE_COLOR PROFILE_ICON | |
| source "$file" | |
| echo "✓ Perfil '$name' activado" | |
| ;; | |
| new) | |
| local name="${2:-}" | |
| [[ -z "$name" ]] && echo "Uso: profile new <nombre>" && return 1 | |
| mkdir -p "$PROFILES_DIR" | |
| local file="$PROFILES_DIR/$name.zsh" | |
| local template="$HOME/.zsh/profile.template.zsh" | |
| [[ -f "$file" ]] && echo "El perfil '$name' ya existe. Usa: profile edit $name" && return 1 | |
| if [[ -f "$template" ]]; then | |
| sed "s/{{NAME}}/$name/g" "$template" > "$file" | |
| else | |
| echo "# ── Perfil: $name ────────────────────────────────────────" > "$file" | |
| fi | |
| echo "✓ Perfil '$name' creado" | |
| $EDITOR "$file" | |
| ;; | |
| edit) | |
| local name="${2:-$(cat "$ACTIVE_PROFILE_FILE" 2>/dev/null)}" | |
| [[ -z "$name" ]] && echo "Sin perfil activo. Uso: profile edit <nombre>" && return 1 | |
| $EDITOR "$PROFILES_DIR/$name.zsh" | |
| ;; | |
| show) | |
| local name; name=$(cat "$ACTIVE_PROFILE_FILE" 2>/dev/null) | |
| [[ -z "$name" ]] && echo "Sin perfil activo" && return 0 | |
| echo " Perfil activo: $name" && echo "" | |
| cat "$PROFILES_DIR/$name.zsh" | |
| ;; | |
| delete|rm) | |
| local name="${2:-}" | |
| [[ -z "$name" ]] && echo "Uso: profile rm <nombre>" && return 1 | |
| local file="$PROFILES_DIR/$name.zsh" | |
| if [[ -f "$file" ]]; then | |
| rm "$file" | |
| echo "✓ Perfil '$name' eliminado ($file)" | |
| # Si era el perfil activo, lo desactivamos para limpiar el ambiente | |
| if [[ "$(cat "$ACTIVE_PROFILE_FILE" 2>/dev/null)" == "$name" ]]; then | |
| rm -f "$ACTIVE_PROFILE_FILE" | |
| unset PROFILE_DISPLAY_NAME PROFILE_COLOR PROFILE_ICON | |
| echo "✓ El perfil estaba activo y ha sido desactivado" | |
| fi | |
| else | |
| echo "✗ Perfil '$name' no existe" | |
| fi | |
| ;; | |
| off) | |
| rm -f "$ACTIVE_PROFILE_FILE" | |
| unset PROFILE_DISPLAY_NAME PROFILE_COLOR PROFILE_ICON | |
| echo "✓ Perfil desactivado" | |
| ;; | |
| *) | |
| echo "Uso: profile [list|use <n>|new <n>|rm <n>|edit [n]|show|off]" | |
| ;; | |
| esac | |
| } | |
| # Auto-cargar perfil activo al iniciar shell | |
| if [[ -f "$ACTIVE_PROFILE_FILE" ]]; then | |
| _pn=$(< "$ACTIVE_PROFILE_FILE") | |
| _pf="$PROFILES_DIR/$_pn.zsh" | |
| [[ -f "$_pf" ]] && source "$_pf" | |
| unset _pn _pf | |
| fi | |
| # ── Configuraciones Locales / Privadas ──────────────────────────── | |
| # Útil para exportar tokens, credenciales o paths sin comitearlos | |
| if [ -f "$HOME/.zshrc.local" ]; then | |
| source "$HOME/.zshrc.local" | |
| fi | |
| ZSHRC_CONTENT | |
| ok ".zshrc generado correctamente" | |
| # Reemplazar placeholder de GIST_RAW_URL en el .zshrc generado | |
| # sed -i necesita extensión vacía en macOS; en Linux funciona sin ella | |
| if [[ "$OS_TYPE" == "macos" ]]; then | |
| sed -i '' "s|__GIST_RAW_URL__|$GIST_RAW_URL|g" "$ZSHRC" | |
| else | |
| sed -i "s|__GIST_RAW_URL__|$GIST_RAW_URL|g" "$ZSHRC" | |
| fi | |
| ok "GIST_RAW_URL configurado en .zshrc ($GIST_RAW_URL)" | |
| # Configurar git-delta si está disponible | |
| if command -v delta &>/dev/null; then | |
| git config --global core.pager "delta" | |
| git config --global interactive.diffFilter "delta --color-only" | |
| git config --global delta.navigate true | |
| git config --global delta.light false | |
| git config --global merge.conflictstyle diff3 | |
| git config --global diff.colorMoved default | |
| ok "git-delta configurado globalmente" | |
| fi | |
| fi | |
| # ================================================================ | |
| # BLOQUE 7: PERFILES DE ENTORNO | |
| # ================================================================ | |
| if [[ "$MODE_FULL" == true || "$MODE_CONFIG" == true ]]; then | |
| section "7/7 — Perfiles de entorno (Cloud)" | |
| PROFILES_BASE="$HOME/.zsh/profiles" | |
| mkdir -p "$PROFILES_BASE" | |
| # Crear template base si no existe | |
| PROFILE_TEMPLATE="$HOME/.zsh/profile.template.zsh" | |
| if [[ ! -f "$PROFILE_TEMPLATE" ]]; then | |
| cat > "$PROFILE_TEMPLATE" << 'EOF' | |
| # ── Perfil: {{NAME}} ──────────────────────────────────────── | |
| # ── Metadatos del Prompt (Spaceship) ──────── | |
| # PROFILE_DISPLAY_NAME="{{NAME}}" | |
| # PROFILE_COLOR="green" # blue, red, yellow, cyan, magenta, etc. | |
| # PROFILE_ICON="🚀" | |
| # ── Variables de Entorno ──────────────────── | |
| # export ENVIRONMENT="development" | |
| # ── Google Cloud / Firebase ───────────────── | |
| # export GOOGLE_CLOUD_PROJECT="" | |
| # export FIREBASE_PROJECT="" | |
| # export GOOGLE_APPLICATION_CREDENTIALS="" | |
| # ── AWS ───────────────────────────────────── | |
| # export AWS_PROFILE="" | |
| # export AWS_REGION="us-east-1" | |
| # ── Aliases específicos del perfil ────────── | |
| # alias deploy="" | |
| EOF | |
| ok "Template de perfil creado en $PROFILE_TEMPLATE" | |
| fi | |
| for _profile_name in default gcloud aws firebase; do | |
| _profile_file="$PROFILES_BASE/$_profile_name.zsh" | |
| if [[ ! -f "$_profile_file" ]]; then | |
| case "$_profile_name" in | |
| default) | |
| cat > "$_profile_file" << 'EOF' | |
| # ── Perfil: default ────────────────────────────────────────── | |
| # Sin configuración de nube — entorno local limpio | |
| # export ENVIRONMENT="local" | |
| EOF | |
| ;; | |
| gcloud) | |
| cat > "$_profile_file" << 'EOF' | |
| # ── Perfil: gcloud ─────────────────────────────────────────── | |
| # Google Cloud Platform | |
| # export GOOGLE_CLOUD_PROJECT="mi-proyecto-id" | |
| # export GOOGLE_APPLICATION_CREDENTIALS="$HOME/.config/gcloud/application_default_credentials.json" | |
| # gcloud config set project "$GOOGLE_CLOUD_PROJECT" 2>/dev/null | |
| # alias deploy='gcloud app deploy' | |
| EOF | |
| ;; | |
| aws) | |
| cat > "$_profile_file" << 'EOF' | |
| # ── Perfil: aws ────────────────────────────────────────────── | |
| # Amazon Web Services | |
| # export AWS_PROFILE="default" | |
| # export AWS_REGION="us-east-1" | |
| # export AWS_DEFAULT_REGION="$AWS_REGION" | |
| EOF | |
| ;; | |
| firebase) | |
| cat > "$_profile_file" << 'EOF' | |
| # ── Perfil: firebase ───────────────────────────────────────── | |
| # Firebase / Google Cloud | |
| # export FIREBASE_PROJECT="mi-proyecto" | |
| # export GOOGLE_APPLICATION_CREDENTIALS="$HOME/.config/firebase/service-account.json" | |
| # alias fdeploy='firebase deploy --project "$FIREBASE_PROJECT"' | |
| EOF | |
| ;; | |
| esac | |
| ok "Perfil '$_profile_name' creado" | |
| else | |
| ok "Perfil '$_profile_name' ya existe \u2014 saltando" | |
| fi | |
| done | |
| unset _profile_name _profile_file | |
| fi # end MODE_FULL || MODE_CONFIG guard | |
| echo "" | |
| log "Usa 'profile list' para ver los perfiles disponibles" | |
| log "Usa 'profile use gcloud' para activar un perfil" | |
| # ================================================================ | |
| # RESUMEN FINAL | |
| # ================================================================ | |
| section "✅ Setup completado" | |
| echo "" | |
| if [[ "$MODE_FULL" == true ]]; then | |
| echo -e "${GREEN}Instalado:${NC}" | |
| echo " ✦ Oh My Zsh" | |
| echo " ✦ Spaceship Prompt v4 (async)" | |
| echo " ✦ zsh-autosuggestions" | |
| echo " ✦ zsh-syntax-highlighting" | |
| echo " ✦ zsh-completions" | |
| echo " ✦ zsh-history-substring-search" | |
| echo " ✦ you-should-use" | |
| echo " ✦ fzf · zoxide · bat · gh · jq · git-delta · direnv" | |
| fi | |
| echo "" | |
| echo -e "${CYAN}Archivos de configuración:${NC}" | |
| echo " ~/.zshrc → configuración principal" | |
| echo " ~/.config/spaceship/spaceship.zsh → prompt Spaceship" | |
| echo "" | |
| echo -e "${YELLOW}Para activar todo:${NC}" | |
| echo " source ~/.zshrc" | |
| echo " (o abrir una nueva terminal)" | |
| echo "" | |
| echo -e "${BLUE}Modos disponibles:${NC}" | |
| printf " %-30s %s\n" "bash setup.sh" "instalación completa desde cero" | |
| printf " %-30s %s\n" "bash setup.sh --plugins" "solo reinstala plugins externos" | |
| printf " %-30s %s\n" "bash setup.sh --config" "regenera .zshrc y spaceship.zsh" | |
| printf " %-30s %s\n" "bash setup.sh --update" "actualiza plugins + Spaceship (git pull)" | |
| echo "" | |
| echo -e "${BLUE}Atajos clave:${NC}" | |
| printf " %-20s %s\n" "→" "Aceptar sugerencia completa" | |
| printf " %-20s %s\n" "Ctrl+R" "Buscar en historial (fzf)" | |
| printf " %-20s %s\n" "Ctrl+T" "Buscar archivos (fzf)" | |
| printf " %-20s %s\n" "Alt+C" "Navegar directorios (fzf)" | |
| printf " %-20s %s\n" "↑ / ↓" "Historial por substring" | |
| printf " %-20s %s\n" "Esc Esc" "Añadir sudo al comando anterior" | |
| printf " %-20s %s\n" "pi" "Info del proyecto git actual" | |
| printf " %-20s %s\n" "reload" "Recargar .zshrc sin cerrar terminal" | |
| echo "" | |
| echo -e "${YELLOW}⚠️ IMPORTANTE: Configura tu terminal (iTerm2/Linux) para usar una Nerd Font (ej. FiraCode Nerd Font) o los íconos se verán rotos.${NC}" | |
| echo -e "${YELLOW}👉 Test de íconos: (Node) | (Rust) | (Git) | (Python) | 🐳 (Docker) ${NC}" | |
| echo "" | |
| echo -e "${GREEN}¡Listo! 🚀 Ejecuta: source ~/.zshrc${NC}" | |
| echo "" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment