diff --git a/.zshrc b/.zshrc index d258436..0b85ec8 100644 --- a/.zshrc +++ b/.zshrc @@ -1,41 +1,59 @@ # ============================================================================= -# CONFIGURACIÓN ZSH - OMARCHY v2.1 +# CONFIGURACIÓN ZSH - Marco Gallegos v3.0 +# ============================================================================= +# +# Este archivo configura el entorno de la terminal Zsh. Incluye la +# configuración del PATH, la carga de Oh My Zsh, la inicialización de +# Oh My Posh, y una colección de alias y funciones para mejorar la +# productividad. +# # ============================================================================= # --- PATH -------------------------------------------------------------------- +# Define las rutas donde el sistema buscará los programas ejecutables. +# `typeset -U` se asegura de que no haya rutas duplicadas. typeset -U PATH path path=( - $HOME/.local/bin - $HOME/bin - $HOME/.npm-global/bin - $HOME/AppImages - $HOME/go/bin - $path + $HOME/.local/bin # Scripts y binarios instalados por el usuario. + $HOME/bin # Directorio personal de binarios. + $HOME/.npm-global/bin # Paquetes de Node.js instalados globalmente. + $HOME/AppImages # Aplicaciones en formato AppImage. + $HOME/go/bin # Binarios de Go. + $path # Rutas del sistema existentes. ) # --- Oh My Zsh --------------------------------------------------------------- +# Configuración y carga del framework Oh My Zsh. export ZSH="$HOME/.oh-my-zsh" -ZSH_THEME="" # Oh My Posh manejará el prompt, así que el tema de OMZ queda vacío. +# El tema se deja vacío porque Oh My Posh se encargará de gestionar el prompt. +ZSH_THEME="" +# Lista de plugins de Oh My Zsh a cargar. plugins=( git sudo history colorize docker docker-compose npm node python pip golang copypath copyfile - # Si usas zoxide, no lo añadas aquí, se inicializa más abajo ) +# Desactiva la comprobación de seguridad de Oh My Zsh para directorios +# con permisos de escritura para otros usuarios, lo que puede ser molesto. export ZSH_DISABLE_COMPFIX=true +# Configuración de la caché de autocompletado para mejorar el rendimiento. zstyle ':completion::complete:*' use-cache on zstyle ':completion::complete:*' cache-path "$HOME/.zcompcache" +# Hace que el autocompletado no distinga entre mayúsculas y minúsculas. zstyle ':completion:*' matcher-list 'm:{a-z}={A-Za-z}' +# Habilita colores en el menú de autocompletado. zstyle ':completion:*' list-colors "${(s.:.)LS_COLORS}" zstyle ':completion:*' menu select -# Cargar Oh My Zsh +# Carga Oh My Zsh. [ -r "$ZSH/oh-my-zsh.sh" ] && source "$ZSH/oh-my-zsh.sh" -# Cargar plugins específicos (zsh-autosuggestions y zsh-syntax-highlighting) +# Carga los plugins de resaltado de sintaxis y autosugerencias. +# Intenta cargar la versión instalada con Oh My Zsh y, si no la encuentra, +# busca la versión instalada en el sistema. [ -r "${ZSH_CUSTOM:-$ZSH/custom}/plugins/zsh-autosuggestions/zsh-autosuggestions.zsh" ] && \ source "${ZSH_CUSTOM:-$ZSH/custom}/plugins/zsh-autosuggestions/zsh-autosuggestions.zsh" if [ ! -r "${ZSH_CUSTOM:-$ZSH/custom}/plugins/zsh-autosuggestions/zsh-autosuggestions.zsh" ] && \ @@ -51,33 +69,34 @@ if [ ! -r "${ZSH_CUSTOM:-$ZSH/custom}/plugins/zsh-syntax-highlighting/zsh-syntax fi # --- Oh My Posh -------------------------------------------------------------- -# Asegúrate de que Oh My Posh esté instalado y el tema 'catppuccin_frappe.omp.json' -# esté en ~/.poshthemes/ +# Inicializa Oh My Posh para personalizar el prompt. if command -v oh-my-posh >/dev/null 2>&1; then + # Carga el tema Catppuccin Frappe si existe. if [ -f ~/.poshthemes/catppuccin_frappe.omp.json ]; then eval "$(oh-my-posh init zsh --config ~/.poshthemes/catppuccin_frappe.omp.json)" else - # Fallback si el tema Catppuccin Frappe no se encuentra + # Si no, carga el tema por defecto. eval "$(oh-my-posh init zsh)" - echo "Advertencia: Tema Catppuccin Frappe para Oh My Posh no encontrado en ~/.poshthemes/. Usando el tema por defecto." fi fi # --- Go ---------------------------------------------------------------------- +# Configura las variables de entorno para el lenguaje de programación Go. export GOPATH="$HOME/go" export GOBIN="$GOPATH/bin" -# --- NVM --------------------------------------------------------------------- -# Es importante que NVM se cargue después de la configuración de PATH, -# pero antes de que intentes usar 'node' o 'npm'. +# --- NVM (Node Version Manager) ---------------------------------------------- +# Carga NVM para gestionar múltiples versiones de Node.js. export NVM_DIR="$HOME/.nvm" -[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" # Esto carga nvm -[ -s "$NVM_DIR/bash_completion" ] && . "$NVM_DIR/bash_completion" # Esto carga nvm bash_completion +[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" +[ -s "$NVM_DIR/bash_completion" ] && . "$NVM_DIR/bash_completion" # --- Python ------------------------------------------------------------------ +# Alias para usar las versiones 3 de python y pip por defecto. alias pip='pip3' alias python='python3' +# Función para gestionar entornos virtuales de Python. venv() { case "$1" in create) python -m venv .venv && echo "✅ Entorno virtual creado en ./.venv" ;; @@ -102,6 +121,9 @@ venv() { } # --- Aliases ----------------------------------------------------------------- +# Colección de atajos para comandos comunes. + +# Generales alias cls='clear' alias ll='ls -alF' alias la='ls -A' @@ -110,17 +132,17 @@ alias ..='cd ..' alias ...='cd ../..' alias ....='cd ../../..' -# System info -alias ff='fastfetch' # Requiere fastfetch -alias nf='fastfetch' # Requiere fastfetch +# Información del sistema +alias ff='fastfetch' +alias nf='fastfetch' -# Arch Linux (si aplica) +# Gestión de paquetes en Arch Linux alias pacu='sudo pacman -Syu' alias paci='sudo pacman -S' alias pacr='sudo pacman -Rns' alias pacs='pacman -Ss' -alias yayu='yay -Syu' # Requiere yay AUR helper -alias yayi='yay -S' # Requiere yay AUR helper +alias yayu='yay -Syu' # Requiere yay +alias yayi='yay -S' # Requiere yay # Git alias gs='git status' @@ -137,7 +159,7 @@ alias glog='git log --oneline --graph --decorate' gac(){ git add . && git commit -m "$1"; } # Docker -# Detecta si se usa 'docker compose' o 'docker-compose' +# Detecta si se usa `docker compose` (nuevo) o `docker-compose` (antiguo). docker compose version >/dev/null 2>&1 && alias dc='docker compose' || alias dc='docker-compose' alias d='docker' alias dps='docker ps -a' @@ -165,43 +187,59 @@ alias zt='sudo zerotier-cli' alias ztstatus='sudo zerotier-cli listnetworks' alias ztinfo='sudo zerotier-cli info' -# Clima (requiere curl) +# Utilidades alias clima='curl wttr.in/Saltillo' +# --- IA y ChatGPT ------------------------------------------------------------ +# Alias para un cliente de ChatGPT en la terminal (ej. 'chatgpt-cli'). +# Reemplaza 'chatgpt-cli' por el nombre del programa que uses. +# +# alias chat='chatgpt-cli' +# alias chat-q='chatgpt-cli -q' # Para una pregunta rápida sin guardar en el historial. +# alias chat-c='chatgpt-cli --continue' # Para continuar la conversación anterior. +# alias chat-code='chatgpt-cli --code' # Para preguntas de código. + # --- Funciones --------------------------------------------------------------- +# Funciones personalizadas para tareas comunes. + +# Crea un directorio y se mueve a él. mkcd(){ mkdir -p "$1" && cd "$1"; } +# Extrae cualquier tipo de archivo comprimido. extract(){ [ ! -f "$1" ] && echo "No es un archivo" && return 1 case "$1" in *.tar.bz2) tar xjf "$1" ;; *.tar.gz) tar xzf "$1" ;; *.bz2) bunzip2 "$1" ;; - *.rar) unrar e "$1" ;; # Requiere 'unrar' + *.rar) unrar e "$1" ;; *.gz) gunzip "$1" ;; *.tar) tar xf "$1" ;; *.tbz2) tar xjf "$1" ;; *.tgz) tar xzf "$1" ;; *.zip) unzip "$1" ;; *.Z) uncompress "$1" ;; - *.7z) 7z x "$1" ;; # Requiere '7zip' - *) echo "No se puede extraer '$1': formato no reconocido o herramienta no instalada." ;; + *.7z) 7z x "$1" ;; + *) echo "No se puede extraer '$1': formato no reconocido." ;; esac } +# Mata el proceso que esté usando un puerto específico. killport(){ [ $# -eq 0 ] && echo "Uso: killport " && return 1 - local pid=$(lsof -ti:"$1" 2>/dev/null) # Requiere 'lsof' + local pid=$(lsof -ti:"$1" 2>/dev/null) [ -n "$pid" ] && kill -9 "$pid" && echo "✅ Proceso en puerto $1 eliminado (PID: $pid)" || echo "🤷 No se encontró ningún proceso en el puerto $1" } +# Inicia un servidor HTTP simple en el directorio actual. serve(){ python -m http.server "${1:-8000}"; } -# --- yt-dlp MEJORADO --------------------------------------------------------- -# Requiere yt-dlp instalado +# --- yt-dlp (Descargador de vídeos) ------------------------------------------ +# Funciones mejoradas para descargar audio y video desde YouTube. export YTDLP_DIR="$HOME/Videos/YouTube" -mkdir -p "$YTDLP_DIR"/{Music,Videos} 2>/dev/null # Crear directorios si no existen +mkdir -p "$YTDLP_DIR"/{Music,Videos} 2>/dev/null +# Descarga audio en formato MP3. ytm() { case "$1" in -h|--help|'') @@ -239,6 +277,7 @@ ytm() { [ $? -eq 0 ] && echo "✅ Audio descargado en: $YTDLP_DIR/Music/" || echo "❌ Falló la descarga de audio." } +# Descarga vídeo en formato MP4. ytv() { case "$1" in -h|--help|'') @@ -287,6 +326,7 @@ ytv() { [ $? -eq 0 ] && echo "✅ Video descargado en: $YTDLP_DIR/Videos/" || echo "❌ Falló la descarga de video." } +# Lista los últimos archivos descargados. ytls() { echo "🎵 Últimos 5 audios descargados en Music:" ls -1t "$YTDLP_DIR/Music" 2>/dev/null | head -5 | sed 's/^/ /' || echo " (vacío)" @@ -295,8 +335,8 @@ ytls() { ls -1t "$YTDLP_DIR/Videos" 2>/dev/null | head -5 | sed 's/^/ /' || echo " (vacío)" } -# --- GNOME Keyring ----------------------------------------------------------- -# Iniciar gnome-keyring-daemon si la sesión es gráfica y no está corriendo +# --- GNOME Keyring y Agente SSH ---------------------------------------------- +# Configuración para que GNOME Keyring gestione las claves SSH. if [ -n "$DESKTOP_SESSION" ] && command -v gnome-keyring-daemon >/dev/null 2>&1; then if ! pgrep -u "$USER" gnome-keyring-daemon > /dev/null 2>&1; then eval "$(gnome-keyring-daemon --start --components=pkcs11,secrets,ssh 2>/dev/null)" || true @@ -304,8 +344,7 @@ if [ -n "$DESKTOP_SESSION" ] && command -v gnome-keyring-daemon >/dev/null 2>&1; export SSH_AUTH_SOCK GPG_AGENT_INFO GNOME_KEYRING_CONTROL GNOME_KEYRING_PID fi -# --- SSH Agent --------------------------------------------------------------- -# Iniciar ssh-agent si no está corriendo y manejar las llaves SSH +# Fallback a un agente SSH estándar si GNOME Keyring no está disponible. if [ -z "$SSH_AUTH_SOCK" ]; then export SSH_AGENT_DIR="$HOME/.ssh/agent" mkdir -p "$SSH_AGENT_DIR" @@ -343,10 +382,10 @@ if [ -z "$SSH_AUTH_SOCK" ]; then fi fi -# Alias útiles para SSH -alias ssh-list='ssh-add -l' # Listar llaves cargadas -alias ssh-clear='ssh-add -D' # Limpiar todas las llaves -alias ssh-reload=' # Recargar todas las llaves +# Alias para gestionar el agente SSH. +alias ssh-list='ssh-add -l' +alias ssh-clear='ssh-add -D' +alias ssh-reload=' ssh-add -D 2>/dev/null for key in ~/.ssh/*; do if [ -f "$key" ] && [[ ! "$key" =~ \.pub$ ]] && ssh-keygen -l -f "$key" &>/dev/null; then @@ -354,50 +393,36 @@ alias ssh-reload=' # Recargar todas las llaves fi done ' - -alias ssh-github='ssh -T git@github.com' # Test GitHub connection +alias ssh-github='ssh -T git@github.com' # --- zoxide ------------------------------------------------------------------ -# Reemplazo inteligente de cd (requiere zoxide) +# Reemplazo inteligente de `cd` que recuerda los directorios que visitas. if command -v zoxide >/dev/null 2>&1; then eval "$(zoxide init zsh)" - - # zoxide se integra con 'cd'. Para usarlo de forma explícita o interactiva, - # puedes usar 'z' y 'zi'. alias zz='z -' # Ir al directorio anterior alias zi='zi' # Modo interactivo -else - echo "Advertencia: zoxide no está instalado. Instálalo para usar 'z', 'zi', 'zz'." fi - # --- Historial de Zsh -------------------------------------------------------- -HISTSIZE=100000 # Número de comandos guardados en el historial en RAM -SAVEHIST=100000 # Número de comandos guardados en el archivo de historial -HISTFILE=~/.zsh_history # Archivo donde se guarda el historial -setopt APPEND_HISTORY # Añadir nuevos comandos al archivo de historial -setopt SHARE_HISTORY # Compartir historial entre sesiones de Zsh -setopt HIST_IGNORE_DUPS # No guardar comandos duplicados consecutivamente -setopt HIST_IGNORE_ALL_DUPS # No guardar comandos duplicados en el historial -setopt HIST_IGNORE_SPACE # No guardar comandos que comienzan con espacio -setopt AUTO_CD # Si se introduce un directorio, cambiar a él -setopt EXTENDED_GLOB # Habilitar características de expansión de comodines extendidas +# Configuración para un historial de comandos más útil y persistente. +HISTSIZE=100000 +SAVEHIST=100000 +HISTFILE=~/.zsh_history +setopt APPEND_HISTORY SHARE_HISTORY HIST_IGNORE_DUPS HIST_IGNORE_ALL_DUPS HIST_IGNORE_SPACE AUTO_CD EXTENDED_GLOB -stty -ixon 2>/dev/null # Deshabilita CTRL+S (pause) y CTRL+Q (resume) +# Deshabilita el bloqueo de la terminal con CTRL+S. +stty -ixon 2>/dev/null -export LESS='-R' # Habilita colores en man pages y less +# Habilita colores en `man` y `less`. +export LESS='-R' -# --- Funciones externas ------------------------------------------------------ -# Cargar cualquier archivo .zsh que se encuentre en ~/.zsh_functions/ +# --- Funciones y Configuraciones Locales ------------------------------------- +# Carga archivos de funciones personalizadas desde ~/.zsh_functions/ [ -d "$HOME/.zsh_functions" ] || mkdir -p "$HOME/.zsh_functions" for func_file in "$HOME/.zsh_functions"/*.zsh(N); do source "$func_file" done -# --- Local Overrides --------------------------------------------------------- -# Permite tener un archivo ~/.zshrc.local para configuraciones personales -# sin modificar el archivo principal. Este archivo se cargará al final. +# Carga un archivo de configuración local (~/.zshrc.local) si existe. +# Ideal para añadir variables de entorno y configuraciones privadas. [ -f ~/.zshrc.local ] && source ~/.zshrc.local - -# Mensaje de bienvenida (opcional, puedes borrarlo) -#echo "🌈 Zsh está configurado con Catppuccin Frappe. ¡Disfruta!" diff --git a/.zshrc.local.example b/.zshrc.local.example new file mode 100644 index 0000000..d29406d --- /dev/null +++ b/.zshrc.local.example @@ -0,0 +1,32 @@ +# ============================================================================= +# .zshrc.local - CONFIGURACIONES LOCALES Y PRIVADAS +# ============================================================================= +# +# Este archivo es para tus configuraciones personales, como variables de +# entorno, claves de API y alias privados. +# +# Para usarlo: +# 1. Renombra este archivo a `.zshrc.local`. +# 2. Descomenta y añade tus claves y configuraciones. +# +# El archivo `.zshrc` principal cargará este fichero automáticamente si existe, +# manteniendo tus datos privados separados de la configuración principal. +# +# ============================================================================= + +# --- Claves de API para Modelos de IA --- +# Descomenta las líneas que necesites y añade tus claves. + +# export OPENAI_API_KEY="sk-..." +# export GOOGLE_API_KEY="..." +# export ANTHROPIC_API_KEY="..." + +# --- Otras Variables de Entorno --- +# Ejemplo de una variable para un token de GitHub. +# export GITHUB_TOKEN="ghp_..." + +# --- Alias Personales --- +# Puedes añadir aquí tus propios alias para no modificar el .zshrc principal. +# +# alias miservidor="ssh usuario@servidor.com" +# alias mi-proyecto="cd ~/Rutas/a/mi/proyecto" diff --git a/Readme.md b/Readme.md index b60fbe4..9e9627e 100644 --- a/Readme.md +++ b/Readme.md @@ -558,20 +558,28 @@ ztstatus ### Oh My Posh no se muestra correctamente +Para que el tema de Oh My Posh se visualice correctamente, es **esencial** tener instalada una "Nerd Font". Estas fuentes incluyen los íconos y símbolos especiales que usa el prompt. + +El script **no** instala fuentes automáticamente, pero puedes hacerlo fácilmente con el siguiente comando: + ```bash -# Verificar instalación +# Instalar la fuente recomendada (Meslo LGM Nerd Font) +oh-my-posh font install meslo +``` + +Después de instalar la fuente, **debes configurar tu emulador de terminal** para que la use. Este paso es crucial y varía según la terminal que utilices (por ejemplo, en GNOME Terminal, Konsole, Alacritty, etc., deberás ir a sus preferencias y seleccionar "MesloLGM Nerd Font"). + +**Verificaciones adicionales:** + +```bash +# Verificar que oh-my-posh está instalado which oh-my-posh -oh-my-posh version # Verificar que el tema existe ls ~/.poshthemes/catppuccin_frappe.omp.json -# Verificar que tienes una Nerd Font instalada -# (El script NO instala fuentes automáticamente) -fc-list | grep -i nerd - -# Si no tienes Nerd Font, instala una: -# - Nerd Fonts: https://www.nerdfonts.com/ +# Listar fuentes para confirmar que Meslo está instalada +fc-list | grep -i "meslo" ``` ### El shell no cambió a Zsh diff --git a/modules/apps.sh b/modules/apps.sh index a9a6263..b974a54 100755 --- a/modules/apps.sh +++ b/modules/apps.sh @@ -2,63 +2,190 @@ # =============================================================== # apps.sh - Instalación de aplicaciones esenciales # =============================================================== +# +# Este módulo se encarga de instalar y configurar una amplia gama +# de aplicaciones y herramientas de sistema. +# +# Funciones principales: +# - Instala Homebrew (Linuxbrew) para gestionar paquetes adicionales. +# - Instala paquetes desde los repositorios de Arch (pacman) y desde AUR. +# - Organiza los paquetes por categorías (base, multimedia, red, etc.). +# - Configura drivers para gráficos Intel Iris Xe. +# - Configura GNOME Keyring para la gestión de contraseñas y claves SSH. +# - Habilita servicios del sistema para aplicaciones como keyd, logiops y TeamViewer. +# +# =============================================================== SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" source "${SCRIPT_DIR}/common.sh" +# --------------------------------------------------------------- +# ensure_homebrew_env() +# --------------------------------------------------------------- +# Asegura que el entorno de Homebrew esté configurado correctamente. +# +# Esta función realiza dos tareas principales: +# 1. Carga Homebrew en la sesión de shell actual para que el comando `brew` +# esté disponible inmediatamente después de la instalación. +# 2. Añade la línea de inicialización de Homebrew a los ficheros de +# perfil del usuario (`.profile` y `.zprofile`) para que `brew` +# esté disponible en futuras sesiones de terminal. +# +# Parámetros: +# $1 - Ruta al ejecutable de brew. +# --------------------------------------------------------------- +ensure_homebrew_env() { + local brew_bin="$1" + if [[ ! -x "$brew_bin" ]]; then + return 1 + fi + + # Evalúa `shellenv` para que el resto del módulo pueda usar `brew` + # sin necesidad de reiniciar la shell. + eval "$("$brew_bin" shellenv)" || return 1 + + local shell_snippet='eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"' + local -a appended=() + local -a rc_targets=("${HOME}/.profile") + + # Si el usuario utiliza Zsh, añade también la configuración a .zprofile. + if [[ -n "${SHELL:-}" && "$(basename "${SHELL}")" == "zsh" ]]; then + rc_targets+=("${HOME}/.zprofile") + fi + + for rc_file in "${rc_targets[@]}"; do + if [[ -f "$rc_file" ]] && grep -Fq "$shell_snippet" "$rc_file"; then + continue + fi + { + echo "" + echo "# Configuración añadida por Omarchy Setup para inicializar Homebrew" + echo "$shell_snippet" + } >> "$rc_file" + appended+=("$rc_file") + done + + if [[ ${#appended[@]} -gt 0 ]]; then + log_info "Se añadió la inicialización de Homebrew a: ${appended[*]}." + fi + + return 0 +} + +# --------------------------------------------------------------- +# install_homebrew() +# --------------------------------------------------------------- +# Instala Homebrew (conocido como Linuxbrew en Linux). +# +# Comprueba si Homebrew ya está instalado. Si no lo está, descarga y +# ejecuta el script de instalación oficial de forma no interactiva. +# Después de la instalación, llama a `ensure_homebrew_env` para +# configurar el entorno de shell. +# --------------------------------------------------------------- install_homebrew() { log_step "Instalación de Homebrew (Linuxbrew)" + local brew_path="/home/linuxbrew/.linuxbrew/bin/brew" if command_exists brew; then + brew_path="$(command -v brew)" + fi + + if command_exists brew || [[ -x "$brew_path" ]]; then log_success "Homebrew ya está instalado." + ensure_homebrew_env "${brew_path}" || true return 0 fi log_info "Instalando Homebrew..." - # Instalar de forma no interactiva + # Instala de forma no interactiva para evitar prompts. if NONINTERACTIVE=1 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"; then log_success "Homebrew instalado correctamente." + ensure_homebrew_env "${brew_path}" || log_warning "Homebrew se instaló pero no se pudo configurar la shell automáticamente." else log_error "Falló la instalación de Homebrew." return 1 fi } +# --------------------------------------------------------------- +# install_nvm() +# --------------------------------------------------------------- +# Instala NVM (Node Version Manager). +# +# Descarga y ejecuta el script de instalación oficial de NVM. +# --------------------------------------------------------------- +install_nvm() { + log_step "Instalación de NVM (Node Version Manager)" + + if [[ -d "${HOME}/.nvm" ]]; then + log_success "NVM ya está instalado." + return 0 + fi + + log_info "Instalando NVM..." + if curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash; then + log_success "NVM instalado correctamente." + log_info "Para usar NVM, reinicia tu terminal o ejecuta: source ~/.nvm/nvm.sh" + else + log_error "Falló la instalación de NVM." + return 1 + fi +} + +# --------------------------------------------------------------- +# run_module_main() +# --------------------------------------------------------------- +# Función principal del módulo de instalación de aplicaciones. +# +# Ejecuta una secuencia de tareas para instalar y configurar +# aplicaciones esenciales del sistema. +# --------------------------------------------------------------- run_module_main() { log_step "Instalación de Aplicaciones" # --- Definición de Paquetes --- + # Paquetes base para el sistema y desarrollo. local PACMAN_BASE=( git curl wget base-devel unzip htop fastfetch btop vim nano tmux xdg-utils xdg-user-dirs stow gnome-keyring libsecret seahorse openssh rsync ) + # Paquetes para desarrollo de software. + local PACMAN_DEV=( + python python-pip nodejs npm uv + ) + # Paquetes para reproducción y edición multimedia. local PACMAN_MULTIMEDIA=( vlc vlc-plugins-all libdvdcss audacity inkscape ffmpeg gstreamer gst-plugins-good gst-plugins-bad gst-plugins-ugly yt-dlp ) + # Aplicaciones de red y conectividad. local PACMAN_NETWORK=( filezilla telegram-desktop scrcpy speedtest-cli ) + # Drivers para gráficos Intel (Mesa y Vulkan). local PACMAN_INTEL_GFX=( mesa vulkan-intel lib32-mesa lib32-vulkan-intel ) + # Drivers para aceleración de vídeo por hardware en Intel (VA-API). local PACMAN_INTEL_VIDEO=( intel-media-driver libva-utils libvdpau-va-gl libva-mesa-driver ) + # Soporte para computación GPGPU con OpenCL. local PACMAN_OPENCL=( ocl-icd libclc clinfo ) + # Paquetes a instalar desde el Arch User Repository (AUR). local AUR_PACKAGES=( "visual-studio-code-bin" "cursor-bin" "keyd" "fragments" "logiops" "ltunify" "teamviewer" "intel-compute-runtime" ) + # --- Instalación de Paquetes --- log_info "Actualizando el sistema para evitar conflictos de dependencias..." sudo pacman -Syu --noconfirm || { log_warning "No se pudo completar la actualización del sistema. Pueden ocurrir errores de dependencias." - # Continuamos de todos modos, pero con una advertencia. } log_info "Instalando herramientas base..." @@ -67,6 +194,14 @@ run_module_main() { return 1 } + log_info "Instalando herramientas de desarrollo..." + sudo pacman -S --noconfirm --needed "${PACMAN_DEV[@]}" || { + log_warning "Algunas herramientas de desarrollo no se pudieron instalar" + } + + # Instalar NVM + install_nvm + # Instalar Homebrew install_homebrew @@ -75,6 +210,7 @@ run_module_main() { log_warning "Algunos paquetes multimedia no se pudieron instalar" } + # Configura VLC como el reproductor por defecto para los tipos de archivo más comunes. log_info "Configurando VLC como reproductor predeterminado..." local mime_types=("audio/mpeg" "audio/mp4" "audio/x-wav" "video/mp4" "video/x-matroska" "video/x-msvideo" "video/x-ms-wmv" "video/webm") for type in "${mime_types[@]}"; do @@ -86,14 +222,15 @@ run_module_main() { log_warning "Algunos paquetes de red no se pudieron instalar" } - # Flatpak log_info "Instalando Flatpak..." sudo pacman -S --noconfirm --needed flatpak || { log_warning "Flatpak no se pudo instalar" } + # --- Configuración de Drivers Intel --- log_info "Instalando drivers y codecs para Intel Iris Xe..." + # Instala los headers del kernel si son necesarios para compilar módulos. KVER="$(uname -r)" if [[ ! -d "/usr/lib/modules/${KVER}/build" ]]; then log_info "Instalando headers de kernel..." @@ -117,15 +254,17 @@ run_module_main() { log_warning "Algunos paquetes OpenCL no se pudieron instalar" } + # Crea el fichero de configuración de OpenCL para los drivers de Intel. if [[ ! -f /etc/OpenCL/vendors/intel.icd ]] && [[ -f /usr/lib/intel-opencl/libigdrcl.so ]]; then log_info "Configurando OpenCL para Intel..." sudo mkdir -p /etc/OpenCL/vendors echo "/usr/lib/intel-opencl/libigdrcl.so" | sudo tee /etc/OpenCL/vendors/intel.icd >/dev/null fi + # Actualiza la caché de librerías compartidas. sudo ldconfig || true - # Verificar instalación de drivers + # --- Verificación de Drivers --- log_info "Verificando drivers Intel instalados..." if command_exists vainfo; then log_info "Información de VA-API:" @@ -137,25 +276,30 @@ run_module_main() { clinfo 2>/dev/null | grep -E "Platform Name|Device Name" || true fi + # --- Instalación desde AUR --- log_info "Instalando aplicaciones desde AUR..." log_warning "Este paso puede tardar varios minutos; qt5-webengine y teamviewer descargan y compilan bastante." if ! aur_install_packages "${AUR_PACKAGES[@]}"; then log_warning "Algunas aplicaciones de AUR no se pudieron instalar automáticamente." fi - # Configurar servicios - log_info "Configurando servicios..." + # --- Configuración de Servicios --- + log_info "Configurando servicios del sistema..." + # Configura GNOME Keyring para que actúe como agente de credenciales y SSH. log_info "Configurando GNOME Keyring como agente de credenciales..." mkdir -p "${HOME}/.config/environment.d" cat <<'EOF' > "${HOME}/.config/environment.d/10-gnome-keyring.conf" SSH_AUTH_SOCK=/run/user/$UID/keyring/ssh EOF + # Habilita el servicio de GNOME Keyring para el usuario actual. if systemctl --user enable --now gnome-keyring-daemon.socket gnome-keyring-daemon.service >/dev/null 2>&1; then log_success "GNOME Keyring listo para gestionar contraseñas y claves SSH." else log_warning "No se pudo habilitar gnome-keyring-daemon en systemd de usuario. Verifica que tu sesión use systemd (--user)." fi + + # Inicia el daemon de GNOME Keyring en la sesión actual para que `ssh-add` funcione. if command_exists gnome-keyring-daemon; then local keyring_eval keyring_eval="$(gnome-keyring-daemon --start --components=secrets,ssh 2>/dev/null)" || keyring_eval="" @@ -169,21 +313,16 @@ EOF fi log_info "Vuelve a iniciar sesión para que las variables de entorno del keyring se apliquen." + # Busca claves SSH en ~/.ssh y las añade al agente de GNOME Keyring. if command_exists ssh-add; then local ssh_dir="${HOME}/.ssh" if [[ -d "$ssh_dir" ]]; then + # Encuentra todas las claves privadas válidas. mapfile -t ssh_private_keys < <( find "$ssh_dir" -maxdepth 1 -type f -perm -u=r \ - ! -name "*.pub" \ - ! -name "*-cert.pub" \ - ! -name "known_hosts" \ - ! -name "known_hosts.*" \ - ! -name "authorized_keys" \ - ! -name "config" \ - ! -name "*.old" \ - ! -name "agent" \ - ! -name "*.bak" \ - 2>/dev/null + ! -name "*.pub" ! -name "*-cert.pub" ! -name "known_hosts" \ + ! -name "known_hosts.*" ! -name "authorized_keys" ! -name "config" \ + ! -name "*.old" ! -name "agent" ! -name "*.bak" 2>/dev/null ) if [[ ${#ssh_private_keys[@]} -gt 0 ]]; then log_info "Agregando claves SSH detectadas al keyring (se solicitará la passphrase si aplica)..." @@ -192,23 +331,20 @@ EOF log_warning "No se puede leer la clave $(basename "$key_path"); revísala manualmente." continue fi + # Intenta añadir la clave al agente. if ssh-keygen -y -f "$key_path" >/dev/null 2>&1; then log_info "Registrando clave $(basename "$key_path")..." local spinner_was_active=0 - if [[ ${SPINNER_ACTIVE:-0} -eq 1 ]]; then - spinner_was_active=1 - fi - if declare -F pause_spinner >/dev/null; then - pause_spinner - fi + if [[ ${SPINNER_ACTIVE:-0} -eq 1 ]]; then spinner_was_active=1; fi + if declare -F pause_spinner >/dev/null; then pause_spinner; fi + if SSH_AUTH_SOCK="$SSH_AUTH_SOCK" ssh-add "$key_path"; then log_success "Clave $(basename "$key_path") añadida al keyring." else log_warning "No se pudo añadir la clave $(basename "$key_path")." fi - if (( spinner_was_active )) && declare -F resume_spinner >/dev/null; then - resume_spinner - fi + + if (( spinner_was_active )) && declare -F resume_spinner >/dev/null; then resume_spinner; fi else log_warning "La clave $(basename "$key_path") parece inválida. Se omite." fi @@ -223,25 +359,20 @@ EOF log_warning "ssh-add no está disponible; no se pueden registrar claves en el keyring." fi - # Habilitar keyd si está instalado + # Habilita los servicios de las aplicaciones instaladas. if command_exists keyd; then log_info "Habilitando servicio keyd..." - sudo systemctl enable keyd.service 2>/dev/null || true - sudo systemctl start keyd.service 2>/dev/null || true + sudo systemctl enable --now keyd.service 2>/dev/null || true fi - # Habilitar logiops si está instalado if command_exists logiops; then log_info "Habilitando servicio logiops..." - sudo systemctl enable logiops.service 2>/dev/null || true - sudo systemctl start logiops.service 2>/dev/null || true + sudo systemctl enable --now logiops.service 2>/dev/null || true fi - # Habilitar TeamViewer daemon si está instalado if command_exists teamviewer; then log_info "Habilitando servicio TeamViewer..." - sudo systemctl enable teamviewerd.service 2>/dev/null || true - sudo systemctl start teamviewerd.service 2>/dev/null || true + sudo systemctl enable --now teamviewerd.service 2>/dev/null || true log_success "TeamViewer daemon habilitado e iniciado" fi @@ -249,7 +380,7 @@ EOF return 0 } -# Ejecutar si se llama directamente +# Ejecutar si se llama directamente al script. if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then run_module_main "$@" fi diff --git a/modules/common.sh b/modules/common.sh index dd1e828..e1a0a4b 100755 --- a/modules/common.sh +++ b/modules/common.sh @@ -125,16 +125,26 @@ aur_install_packages() { return 1 fi - local -a base_flags=(--noconfirm --needed --noeditmenu --nodiffmenu --nocleanmenu) + local -a base_flags=(--noconfirm --needed) AUR_HELPER_CMD="$helper" local status=0 case "$helper" in yay) - "$helper" -S "${base_flags[@]}" --answerdiff None --answerclean All --answeredit None --mflags "--noconfirm" --cleanafter "${packages[@]}" + "$helper" -S "${base_flags[@]}" \ + --answerdiff None \ + --answerclean All \ + --answeredit None \ + --mflags "--noconfirm" \ + --cleanafter \ + "${packages[@]}" status=$? ;; paru) - "$helper" -S "${base_flags[@]}" --skipreview --cleanafter --mflags "--noconfirm" "${packages[@]}" + "$helper" -S "${base_flags[@]}" \ + --skipreview \ + --cleanafter \ + --mflags "--noconfirm" \ + "${packages[@]}" status=$? ;; *) diff --git a/modules/zsh-config.sh b/modules/zsh-config.sh index 0f787ee..a134cc6 100755 --- a/modules/zsh-config.sh +++ b/modules/zsh-config.sh @@ -13,6 +13,18 @@ else exit 1 fi +# Opciones comunes para curl con timeout moderado y reintentos breves. +ZSH_CURL_TIMEOUT_OPTS=(--fail --location --silent --show-error --connect-timeout 10 --max-time 60 --retry 2 --retry-delay 2) + +zsh_download_with_timeout() { + local url="$1" + local dest="$2" + if curl "${ZSH_CURL_TIMEOUT_OPTS[@]}" -o "$dest" "$url"; then + return 0 + fi + return 1 +} + install_zsh() { log_step "Configuración Completa de Zsh" @@ -55,10 +67,20 @@ install_zsh() { else log_warning "No se pudo instalar Oh My Posh mediante pacman ni AUR." log_info "Descargando instalador oficial de Oh My Posh..." - if curl -fsSL https://ohmyposh.dev/install.sh | sudo bash -s -- -d /usr/local/bin; then - log_success "Oh My Posh instalado usando el script oficial." + local omp_installer + omp_installer="$(mktemp)" + if [[ -n "$omp_installer" ]] && zsh_download_with_timeout "https://ohmyposh.dev/install.sh" "$omp_installer"; then + if sudo bash "$omp_installer" -d /usr/local/bin; then + log_success "Oh My Posh instalado usando el script oficial." + else + log_error "Falló la instalación de Oh My Posh usando el script oficial." + rm -f "$omp_installer" + return 1 + fi + rm -f "$omp_installer" else - log_error "Fallo la instalación de Oh My Posh usando el script oficial." + rm -f "${omp_installer:-}" + log_error "No se pudo descargar el instalador oficial de Oh My Posh." return 1 fi fi @@ -71,12 +93,25 @@ install_zsh() { local target_ohmyzsh_dir="${target_home}/.oh-my-zsh" if [[ ! -d "$target_ohmyzsh_dir" ]]; then log_info "Instalando Oh My Zsh..." - # Usar RUNZSH=no para evitar que inicie un nuevo shell y CHSH=no para no cambiar el shell aún - if ! env HOME="$target_home" RUNZSH=no CHSH=no \ - sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" "" --unattended --keep-zshrc; then - log_error "Falló la instalación de Oh My Zsh." + local omz_installer + omz_installer="$(mktemp)" + if [[ -z "$omz_installer" ]]; then + log_error "No se pudo crear un archivo temporal para el instalador de Oh My Zsh." return 1 fi + if zsh_download_with_timeout "https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh" "$omz_installer"; then + # Usar RUNZSH=no para evitar que inicie un nuevo shell y CHSH=no para no cambiar el shell aún + if ! env HOME="$target_home" RUNZSH=no CHSH=no sh "$omz_installer" --unattended --keep-zshrc; then + rm -f "$omz_installer" + log_error "Falló la instalación de Oh My Zsh." + return 1 + fi + else + rm -f "$omz_installer" + log_error "No se pudo descargar el instalador de Oh My Zsh." + return 1 + fi + rm -f "$omz_installer" else log_info "Oh My Zsh ya está instalado." fi @@ -115,7 +150,7 @@ install_zsh() { local tmp_download="${target_home}/.zshrc.omarchy-tmp" local source_file="" - if curl -fsSL "${REPO_BASE}/.zshrc" -o "$tmp_download" && [[ -s "$tmp_download" ]]; then + if zsh_download_with_timeout "${REPO_BASE}/.zshrc" "$tmp_download" && [[ -s "$tmp_download" ]]; then source_file="$tmp_download" log_success "Configuración .zshrc descargada desde el repositorio remoto." else @@ -156,7 +191,7 @@ install_zsh() { local posh_theme_local="${SCRIPT_DIR_ROOT}/themes/catppuccin_frappe.omp.json" mkdir -p "$posh_themes_dir" - if curl -fsSL "https://raw.githubusercontent.com/JanDeDobbeleer/oh-my-posh/main/themes/catppuccin_frappe.omp.json" -o "$theme_file"; then + if zsh_download_with_timeout "https://raw.githubusercontent.com/JanDeDobbeleer/oh-my-posh/main/themes/catppuccin_frappe.omp.json" "$theme_file"; then chmod 644 "$theme_file" 2>/dev/null || true log_success "Tema Catppuccin Frappe descargado en $theme_file" else diff --git a/omarchy-setup.sh b/omarchy-setup.sh index 762d26e..725326f 100755 --- a/omarchy-setup.sh +++ b/omarchy-setup.sh @@ -37,10 +37,6 @@ chmod +x "${MODULES_DIR}"/*.sh 2>/dev/null || true SPINNER_ACTIVE=0 SPINNER_MESSAGE= -spinner_clear_line() { - : -} - pause_spinner() { if (( SPINNER_ACTIVE )); then SPINNER_ACTIVE=0 @@ -141,8 +137,23 @@ MODULES=( ["H"]="hyprland-config;run_module_main;🎨 Instalar Configuración de Hyprland;bg" ) +# Módulos a excluir de la opción "Instalar Todo" +EXCLUDED_FROM_ALL=("R") + +# Generar dinámicamente la lista de módulos para "Instalar Todo" +get_install_all_choices() { + local choices=() + for key in $(printf '%s\n' "${!MODULES[@]}" | sort -V); do + # Verificar si la clave no está en el array de exclusión + if ! [[ " ${EXCLUDED_FROM_ALL[*]} " =~ " ${key} " ]]; then + choices+=("$key") + fi + done + echo "${choices[@]}" +} + # Módulos a incluir en la opción "Instalar Todo" -INSTALL_ALL_CHOICES=("1" "2" "K" "3" "4" "5" "6" "7" "F" "H") +INSTALL_ALL_CHOICES=($(get_install_all_choices)) # Función para mostrar el menú show_menu() { @@ -160,7 +171,8 @@ show_menu() { echo -e " ${GREEN}${key})${NC} ${description}" done | sort -V - echo -e " ${GREEN}A)${NC} ✅ Instalar Todo (1, 2, 3, 4, 5, 6, 7, F, H)" + local install_all_keys=$(IFS=,; echo "${INSTALL_ALL_CHOICES[*]}") + echo -e " ${GREEN}A)${NC} ✅ Instalar Todo (${install_all_keys//,/, }) (excluye DaVinci)" echo -e " ${GREEN}0)${NC} 🚪 Salir" echo "" echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" @@ -265,9 +277,6 @@ install_all() { local failed=() for choice in "${INSTALL_ALL_CHOICES[@]}"; do - if [[ "$choice" == "R" ]]; then - continue - fi IFS=';' read -r module_file _ description type <<< "${MODULES[$choice]}" if ! ensure_sudo_session; then @@ -337,7 +346,6 @@ main() { export -f stop_spinner export -f pause_spinner export -f resume_spinner - export -f spinner_clear_line export -f ensure_sudo_session while true; do @@ -385,8 +393,9 @@ main() { read -p "Presiona Enter para continuar..." elif [[ "$choice" == "A" ]]; then - log_warning "La opción 'Instalar Todo' ejecutará los módulos: 1, 2, K, 3, 4, 5, 6, 7, F y H." - log_info "DaVinci Resolve (opción R) no se ejecutará en este lote; instálalo aparte cuando ya tengas el ZIP." + local modules_to_install=$(IFS=,; echo "${INSTALL_ALL_CHOICES[*]}") + log_warning "La opción 'Instalar Todo' ejecutará los módulos: ${modules_to_install//,/, }." + log_info "Los módulos excluidos (como DaVinci Resolve) deben instalarse por separado." echo -ne "${BOLD}¿Confirmas que deseas instalar todas las opciones ahora? [s/N]: ${NC}" read -r confirm if [[ "${confirm}" =~ ^[SsYy]$ ]]; then