Skip to content

Instantly share code, notes, and snippets.

@dosjota
Created June 1, 2026 19:31
Show Gist options
  • Select an option

  • Save dosjota/93cd666961e63b5d0b778b0508a81da8 to your computer and use it in GitHub Desktop.

Select an option

Save dosjota/93cd666961e63b5d0b778b0508a81da8 to your computer and use it in GitHub Desktop.
configuracion para terminal
#!/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