From 4b05a949c17140966cdd164929ba82019640fe67 Mon Sep 17 00:00:00 2001 From: Ricardo <31641216+manghidev@users.noreply.github.com> Date: Tue, 1 Jul 2025 08:20:23 -0600 Subject: [PATCH 01/20] feat: implement global command installation and uninstallation scripts --- scripts/install-global-commands.sh | 263 --------------------------- scripts/remote-install.sh | 112 ++++-------- scripts/remote-uninstall.sh | 39 +++- scripts/uninstall-global-commands.sh | 4 +- 4 files changed, 72 insertions(+), 346 deletions(-) mode change 100755 => 100644 scripts/install-global-commands.sh diff --git a/scripts/install-global-commands.sh b/scripts/install-global-commands.sh old mode 100755 new mode 100644 index 933bad9..e69de29 --- a/scripts/install-global-commands.sh +++ b/scripts/install-global-commands.sh @@ -1,263 +0,0 @@ -#!/bin/bash - -# LazyVim Docker Global Commands Installer -# This script installs global commands to use LazyVim Docker from anywhere - -set -e - -# Colors -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -BLUE='\033[0;34m' -NC='\033[0m' - -# Functions -log_info() { - echo -e "${BLUE}[INFO]${NC} $1" -} - -log_success() { - echo -e "${GREEN}[SUCCESS]${NC} $1" -} - -log_warning() { - echo -e "${YELLOW}[WARNING]${NC} $1" -} - -log_error() { - echo -e "${RED}[ERROR]${NC} $1" -} - -# Get the absolute path of the lazyvim-docker directory -LAZYVIM_DOCKER_PATH="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" - -log_info "LazyVim Docker Global Commands Installer" -echo "" -log_info "This will install global 'lazy' commands that you can use from anywhere:" -echo " lazy start -> make start" -echo " lazy enter -> make enter" -echo " lazy stop -> make stop" -echo " lazy status -> make status" -echo " lazy build -> make build" -echo " lazy health -> make health" -echo " lazy help -> make help" -echo " lazy uninstall -> Complete uninstall" -echo "" - -# Check if we're in the correct directory -if [[ ! -f "Makefile" ]] || [[ ! -f "docker-compose.yml" ]]; then - log_error "This script must be run from the lazyvim-docker directory" - exit 1 -fi - -# Function to install for Zsh -install_zsh() { - local shell_config="$HOME/.zshrc" - local marker_start="# LazyVim Docker Global Commands - START" - local marker_end="# LazyVim Docker Global Commands - END" - - # Remove existing installation if present - if grep -q "$marker_start" "$shell_config" 2>/dev/null; then - log_info "Removing existing installation..." - sed -i.bak "/$marker_start/,/$marker_end/d" "$shell_config" - fi - - log_info "Installing global commands for Zsh..." - - # Add the new configuration - cat >> "$shell_config" << EOF - -$marker_start -# LazyVim Docker - Global Commands -# Use 'lazy ' from anywhere to control LazyVim Docker -lazyvim_docker_path="$LAZYVIM_DOCKER_PATH" - -lazy() { - if [[ \$# -eq 0 ]]; then - echo "LazyVim Docker - Global Commands" - echo "" - echo "Usage: lazy " - echo "" - echo "Available commands:" - echo " help Show all available commands" - echo " start Start the container" - echo " enter Enter the container (starts if stopped)" - echo " stop Stop the container" - echo " status Show container status" - echo " health Run health diagnostics" - echo " build Build/rebuild the container" - echo " restart Restart the container" - echo " destroy Destroy everything" - echo " clean Clean up Docker resources" - echo " quick Quick start (build + enter)" - echo " logs Show container logs" - echo " backup Backup configurations" - echo " version Show version" - echo " uninstall Remove global commands" - echo "" - echo "Examples:" - echo " lazy enter # Enter LazyVim from anywhere" - echo " lazy status # Check container status" - echo " lazy health # Run full diagnostics" - echo " lazy uninstall # Remove global commands" - echo "" - return 0 - fi - - local cmd="\$1" - shift - - case "\$cmd" in - help|start|enter|stop|status|health|build|restart|destroy|clean|quick|logs|backup|configure|version) - echo "๐Ÿš€ Running: make \$cmd \$@" - (cd "\$lazyvim_docker_path" && make "\$cmd" "\$@") - ;; - uninstall) - echo "๐Ÿ—‘๏ธ Running uninstaller..." - (cd "\$lazyvim_docker_path" && bash uninstall-global-commands.sh) - ;; - *) - echo "โŒ Unknown command: \$cmd" - echo "๐Ÿ’ก Use 'lazy' to see available commands" - return 1 - ;; - esac -} - -# Tab completion for lazy command -_lazy_completion() { - local commands=(help start enter stop status health build restart destroy clean quick logs backup configure version uninstall) - _describe 'commands' commands -} - -if [[ -n "\$ZSH_VERSION" ]]; then - compdef _lazy_completion lazy -fi -$marker_end -EOF - - log_success "Zsh configuration updated!" -} - -# Function to install for Bash -install_bash() { - local shell_config="$HOME/.bashrc" - local marker_start="# LazyVim Docker Global Commands - START" - local marker_end="# LazyVim Docker Global Commands - END" - - # Remove existing installation if present - if grep -q "$marker_start" "$shell_config" 2>/dev/null; then - log_info "Removing existing installation..." - sed -i.bak "/$marker_start/,/$marker_end/d" "$shell_config" - fi - - log_info "Installing global commands for Bash..." - - # Add the new configuration - cat >> "$shell_config" << EOF - -$marker_start -# LazyVim Docker - Global Commands -# Use 'lazy ' from anywhere to control LazyVim Docker -lazyvim_docker_path="$LAZYVIM_DOCKER_PATH" - -lazy() { - if [[ \$# -eq 0 ]]; then - echo "LazyVim Docker - Global Commands" - echo "" - echo "Usage: lazy " - echo "" - echo "Available commands:" - echo " help Show all available commands" - echo " start Start the container" - echo " enter Enter the container (starts if stopped)" - echo " stop Stop the container" - echo " status Show container status" - echo " health Run health diagnostics" - echo " build Build/rebuild the container" - echo " restart Restart the container" - echo " destroy Destroy everything" - echo " clean Clean up Docker resources" - echo " quick Quick start (build + enter)" - echo " logs Show container logs" - echo " backup Backup configurations" - echo " configure Reconfigure directories and timezone" - echo " version Show version" - echo " uninstall Remove global commands" - echo "" - echo "Examples:" - echo " lazy enter # Enter LazyVim from anywhere" - echo " lazy status # Check container status" - echo " lazy health # Run full diagnostics" - echo " lazy configure # Reconfigure directories and timezone" - echo " lazy uninstall # Remove global commands" - echo "" - return 0 - fi - - local cmd="\$1" - shift - - case "\$cmd" in - help|start|enter|stop|status|health|build|restart|destroy|clean|quick|logs|backup|configure|version) - echo "๐Ÿš€ Running: make \$cmd \$@" - (cd "\$lazyvim_docker_path" && make "\$cmd" "\$@") - ;; - uninstall) - echo "๐Ÿ—‘๏ธ Running uninstaller..." - (cd "\$lazyvim_docker_path" && bash uninstall-global-commands.sh) - ;; - *) - echo "โŒ Unknown command: \$cmd" - echo "๐Ÿ’ก Use 'lazy' to see available commands" - return 1 - ;; - esac -} - -# Tab completion for lazy command (basic) -_lazy_completion() { - local cur="\${COMP_WORDS[COMP_CWORD]}" - local commands="help start enter stop status health build restart destroy clean quick logs backup configure version uninstall" - COMPREPLY=(\$(compgen -W "\$commands" -- "\$cur")) -} - -complete -F _lazy_completion lazy -$marker_end -EOF - - log_success "Bash configuration updated!" -} - -# Detect current shell and install accordingly -if [[ -n "$ZSH_VERSION" ]]; then - install_zsh -elif [[ -n "$BASH_VERSION" ]]; then - install_bash -else - log_warning "Unsupported shell. Installing for Zsh by default..." - install_zsh -fi - -echo "" -log_success "Global commands installed successfully!" -echo "" -log_info "To start using the commands:" -echo "" -if [[ -n "$ZSH_VERSION" ]]; then - echo " source ~/.zshrc" -else - echo " source ~/.bashrc" -fi -echo "" -log_info "Or restart your terminal." -echo "" -log_info "Then you can use from anywhere:" -echo " ${GREEN}lazy enter${NC} # Enter LazyVim" -echo " ${GREEN}lazy status${NC} # Check status" -echo " ${GREEN}lazy health${NC} # Run diagnostics" -echo " ${GREEN}lazy${NC} # Show all commands" -echo "" -log_warning "Note: The 'lazy' command will always execute from:" -echo " $LAZYVIM_DOCKER_PATH" diff --git a/scripts/remote-install.sh b/scripts/remote-install.sh index d0d4600..7b1445e 100755 --- a/scripts/remote-install.sh +++ b/scripts/remote-install.sh @@ -151,78 +151,26 @@ install_application() { # Create global commands create_global_commands() { - print_step "Creating global commands..." + print_step "Installing global commands..." - # Create the main lazy command - cat > "$BIN_DIR/lazy" << 'EOF' -#!/bin/bash - -# LazyVim Docker - Global Command -# This script provides global access to LazyVim Docker functionality - -LAZYVIM_INSTALL_DIR="$HOME/.local/share/lazyvim-docker" - -# Check if installation exists -if [ ! -d "$LAZYVIM_INSTALL_DIR" ]; then - echo "โŒ LazyVim Docker not found. Please reinstall:" - echo " curl -fsSL https://raw.githubusercontent.com/manghidev/lazyvim-docker/main/scripts/remote-install.sh | bash" - exit 1 -fi - -# Change to install directory and run make command -cd "$LAZYVIM_INSTALL_DIR" - -# Handle special commands -case "$1" in - uninstall) - echo "๐Ÿ—‘๏ธ Uninstalling LazyVim Docker..." - bash "$LAZYVIM_INSTALL_DIR/scripts/remote-uninstall.sh" - ;; - update) - echo "๐Ÿ”„ Updating LazyVim Docker..." - bash "$LAZYVIM_INSTALL_DIR/scripts/remote-update.sh" - ;; - *) - # Pass all other commands to make - make "$@" - ;; -esac -EOF - - chmod +x "$BIN_DIR/lazy" - - # Add bin directory to PATH if not already there - add_to_path + # Create bin directory if it doesn't exist + mkdir -p "$BIN_DIR" - print_success "Global command 'lazy' created" -} - -# Add bin directory to PATH -add_to_path() { - local shell_config="" - local path_line="export PATH=\"\$HOME/.local/bin:\$PATH\"" - - # Determine shell config file - if [[ -n "$ZSH_VERSION" ]]; then - shell_config="$HOME/.zshrc" - elif [[ -n "$BASH_VERSION" ]]; then - shell_config="$HOME/.bashrc" - # Also check .bash_profile on macOS - if [[ "$OSTYPE" == "darwin"* ]] && [[ -f "$HOME/.bash_profile" ]]; then - shell_config="$HOME/.bash_profile" - fi + # Run the installer script from the project + cd "$INSTALL_DIR" + chmod +x ./scripts/install-global-commands.sh + if ./scripts/install-global-commands.sh; then + print_success "Global commands installed successfully" else - # Default to .bashrc - shell_config="$HOME/.bashrc" + print_error "Failed to install global commands" + exit 1 fi - # Add to PATH if not already there - if ! grep -q "$HOME/.local/bin" "$shell_config" 2>/dev/null; then - echo "" >> "$shell_config" - echo "# LazyVim Docker - Add local bin to PATH" >> "$shell_config" - echo "$path_line" >> "$shell_config" - print_info "Added $HOME/.local/bin to PATH in $shell_config" - fi + # Ensure .local/bin is in PATH for both shells + setup_local_bin_path "$HOME/.bashrc" + setup_local_bin_path "$HOME/.zshrc" + + print_success "Global 'lazy' command is now available" } # Configure timezone @@ -252,7 +200,8 @@ configure_timezone() { echo " - Asia/Tokyo" echo "" - read -p "Enter your timezone [$default_tz]: " user_tz + printf "Enter your timezone [$default_tz]: " + read user_tz user_tz=${user_tz:-$default_tz} # Update timezone in docker-compose.yml @@ -291,9 +240,9 @@ configure_directories() { # Configure Documents directory echo "๐Ÿ“ Documents Directory:" if [[ -d "$default_docs" ]]; then - read -p "Mount Documents directory ($default_docs)? (Y/n): " -n 1 -r - echo - if [[ ! $REPLY =~ ^[Nn]$ ]]; then + printf "Mount Documents directory ($default_docs)? (Y/n): " + read -r reply + if [[ ! $reply =~ ^[Nn]$ ]]; then print_info "Documents directory will be mounted at /home/developer/Documents" else # Comment out the Documents line @@ -309,10 +258,11 @@ configure_directories() { # Configure Projects directory echo "" echo "๐Ÿ’ป Projects Directory:" - read -p "Do you want to mount a Projects directory? (Y/n): " -n 1 -r - echo - if [[ ! $REPLY =~ ^[Nn]$ ]]; then - read -p "Enter path to your projects directory [$default_projects]: " projects_dir + printf "Do you want to mount a Projects directory? (Y/n): " + read -r reply + if [[ ! $reply =~ ^[Nn]$ ]]; then + printf "Enter path to your projects directory [$default_projects]: " + read projects_dir projects_dir=${projects_dir:-$default_projects} if [[ -d "$projects_dir" ]]; then @@ -333,20 +283,22 @@ configure_directories() { # Configure additional directories echo "" echo "๐Ÿ“‚ Additional Directories:" - read -p "Do you want to mount any additional directories? (y/N): " -n 1 -r - echo - if [[ $REPLY =~ ^[Yy]$ ]]; then + printf "Do you want to mount any additional directories? (y/N): " + read -r reply + if [[ $reply =~ ^[Yy]$ ]]; then local counter=1 while true; do echo "" - read -p "Enter directory path (or 'done' to finish): " custom_dir + printf "Enter directory path (or 'done' to finish): " + read custom_dir if [[ "$custom_dir" == "done" ]]; then break fi if [[ -d "$custom_dir" ]]; then local mount_name=$(basename "$custom_dir") - read -p "Mount as [/home/developer/$mount_name]: " container_path + printf "Mount as [/home/developer/$mount_name]: " + read container_path container_path=${container_path:-"/home/developer/$mount_name"} # Add custom directory to docker-compose.yml diff --git a/scripts/remote-uninstall.sh b/scripts/remote-uninstall.sh index 2e88b47..8331b42 100755 --- a/scripts/remote-uninstall.sh +++ b/scripts/remote-uninstall.sh @@ -96,6 +96,40 @@ remove_installation() { fi } +# Remove global commands from shell configurations +remove_shell_commands() { + print_step "Removing global commands from shell configurations..." + + local configs=("$HOME/.bashrc" "$HOME/.zshrc" "$HOME/.bash_profile") + local marker_start="# LazyVim Docker Global Commands - START" + local marker_end="# LazyVim Docker Global Commands - END" + local removed_any=false + + for config in "${configs[@]}"; do + if [[ -f "$config" ]] && grep -q "$marker_start" "$config" 2>/dev/null; then + print_info "Removing commands from: $config" + + # Create backup + cp "$config" "${config}.backup.$(date +%Y%m%d-%H%M%S)" + + # Remove the section between markers + if [[ "$OSTYPE" == "darwin"* ]]; then + sed -i '' "/$marker_start/,/$marker_end/d" "$config" + else + sed -i "/$marker_start/,/$marker_end/d" "$config" + fi + + removed_any=true + fi + done + + if [[ "$removed_any" == true ]]; then + print_success "Global commands removed from shell configurations" + else + print_info "No global commands found in shell configurations" + fi +} + # Remove global command remove_global_command() { print_step "Removing global command..." @@ -111,7 +145,7 @@ remove_global_command() { # Remove PATH modifications (optional) remove_path_modifications() { echo "" - echo -n "Do you want to remove PATH modifications from shell config? [y/N]: " + printf "Do you want to remove PATH modifications from shell config? [y/N]: " read -r response case "$response" in @@ -151,7 +185,7 @@ confirm_uninstall() { echo " โ€ข Global 'lazy' command" echo " โ€ข All data and configurations" echo "" - echo -n "Are you sure you want to continue? [y/N]: " + printf "Are you sure you want to continue? [y/N]: " read -r response case "$response" in @@ -177,6 +211,7 @@ main() { cleanup_docker remove_installation remove_global_command + remove_shell_commands remove_path_modifications echo "" diff --git a/scripts/uninstall-global-commands.sh b/scripts/uninstall-global-commands.sh index 2eca576..5872914 100755 --- a/scripts/uninstall-global-commands.sh +++ b/scripts/uninstall-global-commands.sh @@ -103,11 +103,13 @@ remove_global_commands() { remove_project_directory() { local project_dir project_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + # Get parent directory (remove /scripts) + project_dir="$(dirname "$project_dir")" echo print_status "Current project directory: $project_dir" echo - echo -n "Do you want to remove the entire LazyVim Docker project directory? [y/N]: " + printf "Do you want to remove the entire LazyVim Docker project directory? [y/N]: " read -r response case "$response" in From 4c2a65dde55a2c3900a9903d8d754746d76f137d Mon Sep 17 00:00:00 2001 From: Ricardo <31641216+manghidev@users.noreply.github.com> Date: Tue, 1 Jul 2025 08:27:52 -0600 Subject: [PATCH 02/20] feat: add global commands installer and interactive configuration tests --- scripts/install-global-commands.sh | 283 +++++++++++++++++++++++++++++ scripts/remote-install.sh | 17 ++ test-interactive.sh | 157 ++++++++++++++++ 3 files changed, 457 insertions(+) create mode 100755 test-interactive.sh diff --git a/scripts/install-global-commands.sh b/scripts/install-global-commands.sh index e69de29..75995fb 100644 --- a/scripts/install-global-commands.sh +++ b/scripts/install-global-commands.sh @@ -0,0 +1,283 @@ +#!/bin/bash + +# LazyVim Docker Global Commands Installer +# This script installs global commands to use LazyVim Docker from anywhere + +set -e + +# Colors +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' + +# Functions +log_info() { + echo -e "${BLUE}[INFO]${NC} $1" +} + +log_success() { + echo -e "${GREEN}[SUCCESS]${NC} $1" +} + +log_warning() { + echo -e "${YELLOW}[WARNING]${NC} $1" +} + +log_error() { + echo -e "${RED}[ERROR]${NC} $1" +} + +# Get the absolute path of the lazyvim-docker directory +LAZYVIM_DOCKER_PATH="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +# Remove the /scripts part from the path +LAZYVIM_DOCKER_PATH="$(dirname "$LAZYVIM_DOCKER_PATH")" + +log_info "LazyVim Docker Global Commands Installer" +echo "" +log_info "This will install global 'lazy' commands that you can use from anywhere:" +echo " lazy start -> make start" +echo " lazy enter -> make enter" +echo " lazy stop -> make stop" +echo " lazy status -> make status" +echo " lazy build -> make build" +echo " lazy health -> make health" +echo " lazy help -> make help" +echo " lazy uninstall -> Complete uninstall" +echo "" + +# Check if we're in the correct directory +if [[ ! -f "$LAZYVIM_DOCKER_PATH/Makefile" ]] || [[ ! -f "$LAZYVIM_DOCKER_PATH/docker-compose.yml" ]]; then + log_error "LazyVim Docker project not found at: $LAZYVIM_DOCKER_PATH" + exit 1 +fi + +# Function to install for Zsh +install_zsh() { + local shell_config="$HOME/.zshrc" + local marker_start="# LazyVim Docker Global Commands - START" + local marker_end="# LazyVim Docker Global Commands - END" + + # Remove existing installation if present + if grep -q "$marker_start" "$shell_config" 2>/dev/null; then + log_info "Removing existing installation from Zsh..." + if [[ "$OSTYPE" == "darwin"* ]]; then + sed -i '' "/$marker_start/,/$marker_end/d" "$shell_config" + else + sed -i "/$marker_start/,/$marker_end/d" "$shell_config" + fi + fi + + log_info "Installing global commands for Zsh..." + + # Add the new configuration + cat >> "$shell_config" << EOF + +$marker_start +# LazyVim Docker - Global Commands +# Use 'lazy ' from anywhere to control LazyVim Docker +lazyvim_docker_path="$LAZYVIM_DOCKER_PATH" + +lazy() { + if [[ \$# -eq 0 ]]; then + echo "LazyVim Docker - Global Commands" + echo "" + echo "Usage: lazy " + echo "" + echo "Available commands:" + echo " help Show all available commands" + echo " start Start the container" + echo " enter Enter the container (starts if stopped)" + echo " stop Stop the container" + echo " status Show container status" + echo " health Run health diagnostics" + echo " build Build/rebuild the container" + echo " restart Restart the container" + echo " destroy Destroy everything" + echo " clean Clean up Docker resources" + echo " quick Quick start (build + enter)" + echo " logs Show container logs" + echo " backup Backup configurations" + echo " version Show version" + echo " configure Reconfigure directories and timezone" + echo " uninstall Remove global commands" + echo "" + echo "Examples:" + echo " lazy enter # Enter LazyVim from anywhere" + echo " lazy build # Build the environment" + return 0 + fi + + local cmd="\$1" + shift + + case "\$cmd" in + help|start|enter|stop|status|health|build|restart|destroy|clean|quick|logs|backup|configure|version) + echo "๐Ÿš€ Running: make \$cmd \$@" + (cd "\$lazyvim_docker_path" && make "\$cmd" "\$@") + ;; + uninstall) + echo "๐Ÿ—‘๏ธ Running uninstaller..." + (cd "\$lazyvim_docker_path" && ./scripts/uninstall-global-commands.sh) + ;; + *) + echo "โŒ Unknown command: \$cmd" + echo "๐Ÿ’ก Use 'lazy' to see available commands" + return 1 + ;; + esac +} + +# Tab completion for lazy command (Zsh) +_lazy_zsh_completion() { + local commands=(help start enter stop status health build restart destroy clean quick logs backup configure version uninstall) + _describe 'lazy commands' commands +} + +compdef _lazy_zsh_completion lazy +$marker_end +EOF + + log_success "Zsh configuration updated!" +} + +# Function to install for Bash +install_bash() { + local shell_config="$HOME/.bashrc" + local marker_start="# LazyVim Docker Global Commands - START" + local marker_end="# LazyVim Docker Global Commands - END" + + # Remove existing installation if present + if grep -q "$marker_start" "$shell_config" 2>/dev/null; then + log_info "Removing existing installation from Bash..." + if [[ "$OSTYPE" == "darwin"* ]]; then + sed -i '' "/$marker_start/,/$marker_end/d" "$shell_config" + else + sed -i "/$marker_start/,/$marker_end/d" "$shell_config" + fi + fi + + log_info "Installing global commands for Bash..." + + # Add the new configuration + cat >> "$shell_config" << EOF + +$marker_start +# LazyVim Docker - Global Commands +# Use 'lazy ' from anywhere to control LazyVim Docker +lazyvim_docker_path="$LAZYVIM_DOCKER_PATH" + +lazy() { + if [[ \$# -eq 0 ]]; then + echo "LazyVim Docker - Global Commands" + echo "" + echo "Usage: lazy " + echo "" + echo "Available commands:" + echo " help Show all available commands" + echo " start Start the container" + echo " enter Enter the container (starts if stopped)" + echo " stop Stop the container" + echo " status Show container status" + echo " health Run health diagnostics" + echo " build Build/rebuild the container" + echo " restart Restart the container" + echo " destroy Destroy everything" + echo " clean Clean up Docker resources" + echo " quick Quick start (build + enter)" + echo " logs Show container logs" + echo " backup Backup configurations" + echo " version Show version" + echo " configure Reconfigure directories and timezone" + echo " uninstall Remove global commands" + echo "" + echo "Examples:" + echo " lazy enter # Enter LazyVim from anywhere" + echo " lazy build # Build the environment" + return 0 + fi + + local cmd="\$1" + shift + + case "\$cmd" in + help|start|enter|stop|status|health|build|restart|destroy|clean|quick|logs|backup|configure|version) + echo "๐Ÿš€ Running: make \$cmd \$@" + (cd "\$lazyvim_docker_path" && make "\$cmd" "\$@") + ;; + uninstall) + echo "๐Ÿ—‘๏ธ Running uninstaller..." + (cd "\$lazyvim_docker_path" && ./scripts/uninstall-global-commands.sh) + ;; + *) + echo "โŒ Unknown command: \$cmd" + echo "๐Ÿ’ก Use 'lazy' to see available commands" + return 1 + ;; + esac +} + +# Tab completion for lazy command (Bash) +_lazy_completion() { + local cur="\${COMP_WORDS[COMP_CWORD]}" + local commands="help start enter stop status health build restart destroy clean quick logs backup configure version uninstall" + COMPREPLY=(\$(compgen -W "\$commands" -- "\$cur")) +} + +complete -F _lazy_completion lazy +$marker_end +EOF + + log_success "Bash configuration updated!" +} + +# Main installation function +install_global_commands() { + log_info "Installing global commands for both Bash and Zsh..." + + # Ensure shell config files exist + touch "$HOME/.bashrc" "$HOME/.zshrc" + + # Install for both shells + install_bash + install_zsh + + echo "" + log_success "โœ“ Global 'lazy' commands installed!" + echo "" + log_info "Commands installed for both Bash and Zsh:" + echo " โ€ข Bash: $HOME/.bashrc" + echo " โ€ข Zsh: $HOME/.zshrc" + echo "" + log_info "Usage:" + echo " lazy enter # Enter LazyVim development environment" + echo " lazy help # Show all available commands" + echo "" + log_info "To activate:" + echo " โ€ข Restart your terminal, or" + echo " โ€ข Run: source ~/.bashrc (for Bash)" + echo " โ€ข Run: source ~/.zshrc (for Zsh)" + echo "" + + # Detect current shell and provide specific activation command + local current_shell="" + if [[ -n "$ZSH_VERSION" ]]; then + current_shell="zsh" + echo -e "${GREEN}For your current Zsh session, run: source ~/.zshrc${NC}" + elif [[ -n "$BASH_VERSION" ]]; then + current_shell="bash" + echo -e "${GREEN}For your current Bash session, run: source ~/.bashrc${NC}" + elif [[ "$SHELL" == *"zsh"* ]]; then + current_shell="zsh" + echo -e "${GREEN}For your current Zsh session, run: source ~/.zshrc${NC}" + else + current_shell="bash" + echo -e "${GREEN}For your current Bash session, run: source ~/.bashrc${NC}" + fi + + echo "" +} + +# Run the installation +install_global_commands diff --git a/scripts/remote-install.sh b/scripts/remote-install.sh index 7b1445e..929e81e 100755 --- a/scripts/remote-install.sh +++ b/scripts/remote-install.sh @@ -149,6 +149,23 @@ install_application() { print_success "Application installed to $INSTALL_DIR" } +# Setup PATH for local bin directory +setup_local_bin_path() { + local shell_config="$1" + local path_line="export PATH=\"\$HOME/.local/bin:\$PATH\"" + + # Create config file if it doesn't exist + touch "$shell_config" + + # Add to PATH if not already there + if ! grep -q "$HOME/.local/bin" "$shell_config" 2>/dev/null; then + echo "" >> "$shell_config" + echo "# LazyVim Docker - Add local bin to PATH" >> "$shell_config" + echo "$path_line" >> "$shell_config" + print_info "Added $HOME/.local/bin to PATH in $shell_config" + fi +} + # Create global commands create_global_commands() { print_step "Installing global commands..." diff --git a/test-interactive.sh b/test-interactive.sh new file mode 100755 index 0000000..115cefc --- /dev/null +++ b/test-interactive.sh @@ -0,0 +1,157 @@ +#!/bin/bash + +# Test Script - Test interactive configuration functions +# This script tests the interactive parts of the remote installer + +set -e + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +PURPLE='\033[0;35m' +CYAN='\033[0;36m' +NC='\033[0m' # No Color + +# Print functions +print_info() { + echo -e "${BLUE}[INFO]${NC} $1" +} + +print_success() { + echo -e "${GREEN}[SUCCESS]${NC} $1" +} + +print_step() { + echo -e "${PURPLE}[STEP]${NC} $1" +} + +# Test timezone configuration +test_configure_timezone() { + print_step "Testing timezone configuration..." + + # Detect system timezone + local system_tz="" + if command -v timedatectl >/dev/null 2>&1; then + system_tz=$(timedatectl show --property=Timezone --value 2>/dev/null || echo "") + elif [[ -f /etc/timezone ]]; then + system_tz=$(cat /etc/timezone 2>/dev/null || echo "") + elif [[ "$OSTYPE" == "darwin"* ]]; then + system_tz=$(ls -la /etc/localtime 2>/dev/null | sed 's/.*zoneinfo\///' || echo "") + fi + + # Default timezone if detection fails + local default_tz="${system_tz:-America/Mexico_City}" + + echo "Current system timezone detected: ${system_tz:-"Could not detect"}" + echo "Available timezone examples:" + echo " - America/New_York" + echo " - America/Los_Angeles" + echo " - America/Mexico_City" + echo " - Europe/London" + echo " - Europe/Madrid" + echo " - Asia/Tokyo" + echo "" + + printf "Enter your timezone [$default_tz]: " + read user_tz + user_tz=${user_tz:-$default_tz} + + print_success "Timezone selected: $user_tz" +} + +# Test directories configuration +test_configure_directories() { + print_step "Testing directories configuration..." + + # Detect OS + local os_type="" + local default_docs="$HOME/Documents" + local default_projects="" + + if [[ "$OSTYPE" == "darwin"* ]]; then + os_type="macOS" + default_projects="$HOME/Developer" + else + os_type="Linux" + default_projects="$HOME/Projects" + fi + + echo "Detected OS: $os_type" + echo "Testing directory mounting configuration..." + echo "" + + # Test Documents directory + echo "๐Ÿ“ Documents Directory:" + if [[ -d "$default_docs" ]]; then + printf "Mount Documents directory ($default_docs)? (Y/n): " + read -r reply + if [[ ! $reply =~ ^[Nn]$ ]]; then + print_info "Documents directory would be mounted at /home/developer/Documents" + else + print_info "Documents directory mounting would be disabled" + fi + fi + + # Test Projects directory + echo "" + echo "๐Ÿ’ป Projects Directory:" + printf "Do you want to mount a Projects directory? (Y/n): " + read -r reply + if [[ ! $reply =~ ^[Nn]$ ]]; then + printf "Enter path to your projects directory [$default_projects]: " + read projects_dir + projects_dir=${projects_dir:-$default_projects} + + if [[ -d "$projects_dir" ]]; then + print_success "Projects directory would be added: $projects_dir -> /home/developer/Projects" + else + print_info "Directory $projects_dir does not exist, but would be configured anyway" + fi + fi + + # Test additional directories + echo "" + echo "๐Ÿ“‚ Additional Directories:" + printf "Do you want to mount any additional directories? (y/N): " + read -r reply + if [[ $reply =~ ^[Yy]$ ]]; then + while true; do + echo "" + printf "Enter directory path (or 'done' to finish): " + read custom_dir + if [[ "$custom_dir" == "done" ]]; then + break + fi + + if [[ -d "$custom_dir" ]]; then + local mount_name=$(basename "$custom_dir") + printf "Mount as [/home/developer/$mount_name]: " + read container_path + container_path=${container_path:-"/home/developer/$mount_name"} + print_success "Would mount: $custom_dir -> $container_path" + else + print_info "Directory $custom_dir does not exist, but would be configured anyway" + fi + done + fi +} + +echo -e "${CYAN}โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—${NC}" +echo -e "${CYAN}โ•‘ LazyVim Docker - Test โ•‘${NC}" +echo -e "${CYAN}โ•‘ Interactive Configuration Test โ•‘${NC}" +echo -e "${CYAN}โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•${NC}" +echo "" + +print_info "This script tests the interactive configuration functions" +print_info "Testing input compatibility for your shell: $(basename "$SHELL")" +echo "" + +test_configure_timezone +echo "" +test_configure_directories + +echo "" +print_success "โœ… All interactive functions work correctly!" +print_info "The configuration prompts are functioning properly in your shell." From 60e16acec50fff67b2fef033729417fd7a8d5e33 Mon Sep 17 00:00:00 2001 From: Ricardo <31641216+manghidev@users.noreply.github.com> Date: Tue, 1 Jul 2025 08:34:51 -0600 Subject: [PATCH 03/20] fix: ensure interactive prompts read from the correct terminal --- scripts/remote-install.sh | 14 +++++++------- scripts/remote-uninstall.sh | 4 ++-- scripts/uninstall-global-commands.sh | 2 +- test-interactive.sh | 14 +++++++------- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/scripts/remote-install.sh b/scripts/remote-install.sh index 929e81e..d5de78d 100755 --- a/scripts/remote-install.sh +++ b/scripts/remote-install.sh @@ -218,7 +218,7 @@ configure_timezone() { echo "" printf "Enter your timezone [$default_tz]: " - read user_tz + read user_tz $container_path" else From 064ddb041a6bdb06c3f558387ef991a9f239512c Mon Sep 17 00:00:00 2001 From: Ricardo <31641216+manghidev@users.noreply.github.com> Date: Tue, 1 Jul 2025 08:41:57 -0600 Subject: [PATCH 04/20] feat: enhance remote installation script with non-interactive mode support --- scripts/remote-install-simple.sh | 326 +++++++++++++++++++++++++++++++ scripts/remote-install.sh | 111 +++++++++-- 2 files changed, 421 insertions(+), 16 deletions(-) create mode 100644 scripts/remote-install-simple.sh diff --git a/scripts/remote-install-simple.sh b/scripts/remote-install-simple.sh new file mode 100644 index 0000000..8d2e146 --- /dev/null +++ b/scripts/remote-install-simple.sh @@ -0,0 +1,326 @@ +#!/bin/bash + +# LazyVim Docker - Simple Remote Installation Script +# This version uses smart defaults and skips interactive configuration +# Perfect for automated installations or when interactive input fails + +set -e + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +PURPLE='\033[0;35m' +CYAN='\033[0;36m' +NC='\033[0m' # No Color + +# Configuration +REPO_URL="https://github.com/manghidev/lazyvim-docker" +REPO_NAME="lazyvim-docker" +INSTALL_DIR="$HOME/.local/share/lazyvim-docker" +BIN_DIR="$HOME/.local/bin" +TEMP_DIR="/tmp/lazyvim-docker-install" +BRANCH="${LAZYVIM_BRANCH:-develop}" + +# Print functions +print_header() { + echo -e "${CYAN}โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—${NC}" + echo -e "${CYAN}โ•‘ LazyVim Docker - Simple Installer โ•‘${NC}" + echo -e "${CYAN}โ•‘ Smart Defaults, Zero Input โ•‘${NC}" + echo -e "${CYAN}โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•${NC}" + echo "" +} + +print_info() { + echo -e "${BLUE}[INFO]${NC} $1" +} + +print_success() { + echo -e "${GREEN}[SUCCESS]${NC} $1" +} + +print_warning() { + echo -e "${YELLOW}[WARNING]${NC} $1" +} + +print_error() { + echo -e "${RED}[ERROR]${NC} $1" +} + +print_step() { + echo -e "${PURPLE}[STEP]${NC} $1" +} + +# Check if command exists +command_exists() { + command -v "$1" >/dev/null 2>&1 +} + +# Check system requirements +check_requirements() { + print_step "Checking system requirements..." + + local missing_deps=() + + if ! command_exists curl; then + missing_deps+=("curl") + fi + + if ! command_exists git; then + missing_deps+=("git") + fi + + if ! command_exists docker; then + missing_deps+=("docker") + fi + + if ! command_exists docker && ! docker compose version >/dev/null 2>&1; then + print_warning "Docker or Docker Compose not found." + if ! docker compose version >/dev/null 2>&1; then + missing_deps+=("docker") + fi + fi + + if [ ${#missing_deps[@]} -ne 0 ]; then + print_error "Missing required dependencies: ${missing_deps[*]}" + echo "" + print_info "Please install the missing dependencies and try again:" + echo "" + if [[ "$OSTYPE" == "darwin"* ]]; then + echo " brew install ${missing_deps[*]}" + elif [[ "$OSTYPE" == "linux"* ]]; then + echo " # Ubuntu/Debian:" + echo " sudo apt-get update && sudo apt-get install -y ${missing_deps[*]}" + echo "" + echo " # CentOS/RHEL:" + echo " sudo yum install -y ${missing_deps[*]}" + fi + echo "" + exit 1 + fi + + print_success "All requirements satisfied!" +} + +# Create installation directories +create_directories() { + print_step "Creating installation directories..." + + mkdir -p "$INSTALL_DIR" + mkdir -p "$BIN_DIR" + mkdir -p "$TEMP_DIR" + + print_success "Directories created successfully" +} + +# Download repository +download_repository() { + print_step "Downloading LazyVim Docker repository..." + + cd "$TEMP_DIR" + + if command_exists git; then + git clone --branch "$BRANCH" --depth 1 "$REPO_URL" "$REPO_NAME" >/dev/null 2>&1 + else + curl -fsSL "${REPO_URL}/archive/${BRANCH}.tar.gz" | tar -xz --strip-components=1 -C "$REPO_NAME" 2>/dev/null + fi + + print_success "Repository downloaded successfully" +} + +# Install application +install_application() { + print_step "Installing LazyVim Docker..." + + if [ -d "$INSTALL_DIR" ]; then + print_info "Removing existing installation..." + rm -rf "$INSTALL_DIR" + fi + + cp -r "$TEMP_DIR/$REPO_NAME" "$INSTALL_DIR" + + print_success "Application installed to $INSTALL_DIR" +} + +# Setup PATH for local bin directory +setup_local_bin_path() { + local shell_config="$1" + local path_line="export PATH=\"\$HOME/.local/bin:\$PATH\"" + + # Create config file if it doesn't exist + touch "$shell_config" + + # Add to PATH if not already there + if ! grep -q "$HOME/.local/bin" "$shell_config" 2>/dev/null; then + echo "" >> "$shell_config" + echo "# LazyVim Docker - Add local bin to PATH" >> "$shell_config" + echo "$path_line" >> "$shell_config" + print_info "Added $HOME/.local/bin to PATH in $shell_config" + fi +} + +# Create global commands +create_global_commands() { + print_step "Installing global commands..." + + # Create bin directory if it doesn't exist + mkdir -p "$BIN_DIR" + + # Run the installer script from the project + cd "$INSTALL_DIR" + chmod +x ./scripts/install-global-commands.sh + if ./scripts/install-global-commands.sh; then + print_success "Global commands installed successfully" + else + print_error "Failed to install global commands" + exit 1 + fi + + # Ensure .local/bin is in PATH for both shells + setup_local_bin_path "$HOME/.bashrc" + setup_local_bin_path "$HOME/.zshrc" + + print_success "Global 'lazy' command is now available" +} + +# Auto-configure with smart defaults +auto_configure() { + print_step "Auto-configuring with smart defaults..." + + cd "$INSTALL_DIR" + + # Detect and set timezone + local system_tz="" + if command -v timedatectl >/dev/null 2>&1; then + system_tz=$(timedatectl show --property=Timezone --value 2>/dev/null || echo "") + elif [[ -f /etc/timezone ]]; then + system_tz=$(cat /etc/timezone 2>/dev/null || echo "") + elif [[ "$OSTYPE" == "darwin"* ]]; then + system_tz=$(ls -la /etc/localtime 2>/dev/null | sed 's/.*zoneinfo\///' || echo "") + fi + + local default_tz="${system_tz:-America/Mexico_City}" + + # Update timezone in docker-compose.yml + if [[ "$OSTYPE" == "darwin"* ]]; then + sed -i '' "s/TIMEZONE: .*/TIMEZONE: $default_tz/" docker-compose.yml + sed -i '' "s/TZ=.*/TZ=$default_tz/" docker-compose.yml + else + sed -i "s/TIMEZONE: .*/TIMEZONE: $default_tz/" docker-compose.yml + sed -i "s/TZ=.*/TZ=$default_tz/" docker-compose.yml + fi + + print_success "Timezone configured: $default_tz" + + # Auto-configure directories + local default_docs="$HOME/Documents" + local default_projects="" + + if [[ "$OSTYPE" == "darwin"* ]]; then + default_projects="$HOME/Developer" + else + default_projects="$HOME/Projects" + fi + + # Configure Documents automatically if exists + if [[ -d "$default_docs" ]]; then + print_success "Documents directory will be mounted: $default_docs" + else + # Comment out the Documents line + if [[ "$OSTYPE" == "darwin"* ]]; then + sed -i '' 's|^ - \$HOME/Documents:| # - \$HOME/Documents:|' docker-compose.yml + else + sed -i 's|^ - \$HOME/Documents:| # - \$HOME/Documents:|' docker-compose.yml + fi + print_info "Documents directory not found, mounting disabled" + fi + + # Configure Projects automatically if exists + if [[ -d "$default_projects" ]]; then + # Add projects directory to docker-compose.yml + if [[ "$OSTYPE" == "darwin"* ]]; then + sed -i '' "/\$HOME\/Documents:/a\\ + - $default_projects:/home/developer/Projects" docker-compose.yml + else + sed -i "/\$HOME\/Documents:/a\\ + - $default_projects:/home/developer/Projects" docker-compose.yml + fi + print_success "Projects directory added: $default_projects" + else + print_info "Projects directory not found: $default_projects" + fi + + print_success "Auto-configuration completed with smart defaults" +} + +# Build environment +build_environment() { + print_step "Building Docker environment..." + + cd "$INSTALL_DIR" + + print_info "This may take a few minutes..." + if make build; then + print_success "Docker environment built successfully" + else + print_warning "Docker build failed, but installation completed. You can run 'lazy build' later." + fi +} + +# Cleanup +cleanup() { + print_step "Cleaning up temporary files..." + rm -rf "$TEMP_DIR" + print_success "Cleanup completed" +} + +# Main installation process +main() { + print_header + + print_info "Starting LazyVim Docker simple installation..." + print_info "Installation directory: $INSTALL_DIR" + print_info "Binary directory: $BIN_DIR" + print_info "Using smart defaults (no interactive input required)" + echo "" + + check_requirements + create_directories + download_repository + install_application + create_global_commands + auto_configure + build_environment + cleanup + + echo "" + print_success "๐ŸŽ‰ LazyVim Docker installed successfully!" + echo "" + print_info "Configuration applied:" + echo " โ€ข Timezone: Auto-detected from system" + echo " โ€ข Documents: Auto-mounted if exists" + echo " โ€ข Projects: Auto-mounted if exists" + echo "" + print_info "Usage:" + echo " ${GREEN}lazy enter${NC} # Enter LazyVim development environment" + echo " ${GREEN}lazy start${NC} # Start the container" + echo " ${GREEN}lazy stop${NC} # Stop the container" + echo " ${GREEN}lazy status${NC} # Check container status" + echo " ${GREEN}lazy configure${NC} # Reconfigure directories and timezone" + echo " ${GREEN}lazy update${NC} # Update to latest version" + echo " ${GREEN}lazy uninstall${NC} # Uninstall everything" + echo " ${GREEN}lazy help${NC} # Show all available commands" + echo "" + print_info "To get started:" + echo " 1. Restart your terminal or run: ${YELLOW}source ~/.zshrc${NC} (or ~/.bashrc)" + echo " 2. Run: ${GREEN}lazy enter${NC}" + echo "" + print_info "To customize configuration later:" + echo " Run: ${GREEN}lazy configure${NC}" + echo "" + print_info "Happy coding! ๐Ÿš€" +} + +# Run main function +main "$@" diff --git a/scripts/remote-install.sh b/scripts/remote-install.sh index d5de78d..9c678fd 100755 --- a/scripts/remote-install.sh +++ b/scripts/remote-install.sh @@ -190,6 +190,40 @@ create_global_commands() { print_success "Global 'lazy' command is now available" } +# Check if we can do interactive input +can_interact() { + if [[ -t 0 ]]; then + # stdin is a terminal + return 0 + elif [[ -c /dev/tty ]] && exec < /dev/tty 2>/dev/null; then + # /dev/tty is available + return 0 + else + # No interactive input possible + return 1 + fi +} + +# Safe interactive read +safe_read() { + local prompt="$1" + local default="$2" + local result="" + + if can_interact; then + printf "%s" "$prompt" + if [[ -c /dev/tty ]]; then + read result /dev/null || read result + else + read result + fi + echo "${result:-$default}" + else + print_warning "Running in non-interactive mode, using default: $default" + echo "$default" + fi +} + # Configure timezone configure_timezone() { print_step "Configuring timezone..." @@ -217,9 +251,13 @@ configure_timezone() { echo " - Asia/Tokyo" echo "" - printf "Enter your timezone [$default_tz]: " - read user_tz /dev/null || exec < /dev/stdin + fi +} + # Main installation process main() { + # Handle stdin redirection first + handle_stdin + print_header print_info "Starting LazyVim Docker remote installation..." From e41a2c08b6a320942c0da553ec8a127a5eb032a5 Mon Sep 17 00:00:00 2001 From: Ricardo <31641216+manghidev@users.noreply.github.com> Date: Tue, 1 Jul 2025 08:49:56 -0600 Subject: [PATCH 05/20] fix: update sed commands in timezone configuration to use pipe delimiters for safety test: add script to verify sed commands work with timezone values --- scripts/remote-install-simple.sh | 8 +++---- scripts/remote-install.sh | 8 +++---- test-sed.sh | 36 ++++++++++++++++++++++++++++++++ 3 files changed, 44 insertions(+), 8 deletions(-) create mode 100644 test-sed.sh diff --git a/scripts/remote-install-simple.sh b/scripts/remote-install-simple.sh index 8d2e146..7535fcb 100644 --- a/scripts/remote-install-simple.sh +++ b/scripts/remote-install-simple.sh @@ -204,11 +204,11 @@ auto_configure() { # Update timezone in docker-compose.yml if [[ "$OSTYPE" == "darwin"* ]]; then - sed -i '' "s/TIMEZONE: .*/TIMEZONE: $default_tz/" docker-compose.yml - sed -i '' "s/TZ=.*/TZ=$default_tz/" docker-compose.yml + sed -i '' "s|TIMEZONE: .*|TIMEZONE: $default_tz|" docker-compose.yml + sed -i '' "s|TZ=.*|TZ=$default_tz|" docker-compose.yml else - sed -i "s/TIMEZONE: .*/TIMEZONE: $default_tz/" docker-compose.yml - sed -i "s/TZ=.*/TZ=$default_tz/" docker-compose.yml + sed -i "s|TIMEZONE: .*|TIMEZONE: $default_tz|" docker-compose.yml + sed -i "s|TZ=.*|TZ=$default_tz|" docker-compose.yml fi print_success "Timezone configured: $default_tz" diff --git a/scripts/remote-install.sh b/scripts/remote-install.sh index 9c678fd..841eab2 100755 --- a/scripts/remote-install.sh +++ b/scripts/remote-install.sh @@ -261,11 +261,11 @@ configure_timezone() { # Update timezone in docker-compose.yml if [[ "$OSTYPE" == "darwin"* ]]; then - sed -i '' "s/TIMEZONE: .*/TIMEZONE: $user_tz/" docker-compose.yml - sed -i '' "s/TZ=.*/TZ=$user_tz/" docker-compose.yml + sed -i '' "s|TIMEZONE: .*|TIMEZONE: $user_tz|" docker-compose.yml + sed -i '' "s|TZ=.*|TZ=$user_tz|" docker-compose.yml else - sed -i "s/TIMEZONE: .*/TIMEZONE: $user_tz/" docker-compose.yml - sed -i "s/TZ=.*/TZ=$user_tz/" docker-compose.yml + sed -i "s|TIMEZONE: .*|TIMEZONE: $user_tz|" docker-compose.yml + sed -i "s|TZ=.*|TZ=$user_tz|" docker-compose.yml fi print_success "Timezone configured: $user_tz" diff --git a/test-sed.sh b/test-sed.sh new file mode 100644 index 0000000..3493d0b --- /dev/null +++ b/test-sed.sh @@ -0,0 +1,36 @@ +#!/bin/bash + +# Test script to verify sed commands work with timezone values + +echo "Testing sed commands with timezone values..." + +# Create a test docker-compose.yml +cat > test-compose.yml << 'EOF' +services: + test: + environment: + - TIMEZONE: America/New_York + - TZ=America/New_York +EOF + +echo "Original file:" +cat test-compose.yml + +echo "" +echo "Testing with America/Chihuahua..." + +# Test with problematic timezone +timezone="America/Chihuahua" + +# Using pipe delimiters (safe) +sed -i.bak "s|TIMEZONE: .*|TIMEZONE: $timezone|" test-compose.yml +sed -i.bak2 "s|TZ=.*|TZ=$timezone|" test-compose.yml + +echo "After sed commands:" +cat test-compose.yml + +echo "" +echo "โœ… sed commands work correctly with pipe delimiters" + +# Cleanup +rm -f test-compose.yml test-compose.yml.bak test-compose.yml.bak2 From e02a8585e8b98823bc1fb298d4112b153d3b8ee9 Mon Sep 17 00:00:00 2001 From: Ricardo <31641216+manghidev@users.noreply.github.com> Date: Tue, 1 Jul 2025 09:13:15 -0600 Subject: [PATCH 06/20] feat: improve prompt consistency in interactive scripts and add test script for verification --- scripts/remote-install.sh | 15 ++++++--------- test-prompts.sh | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 9 deletions(-) create mode 100644 test-prompts.sh diff --git a/scripts/remote-install.sh b/scripts/remote-install.sh index 841eab2..7c6e2c8 100755 --- a/scripts/remote-install.sh +++ b/scripts/remote-install.sh @@ -204,7 +204,7 @@ can_interact() { fi } -# Safe interactive read +# Safe interactive read with consistent format safe_read() { local prompt="$1" local default="$2" @@ -241,6 +241,7 @@ configure_timezone() { # Default timezone if detection fails local default_tz="${system_tz:-America/Mexico_City}" + echo "๐ŸŒ Timezone Configuration:" echo "Current system timezone detected: ${system_tz:-"Could not detect"}" echo "Available timezone examples:" echo " - America/New_York" @@ -327,12 +328,10 @@ configure_directories() { return fi - - # Interactive mode - # Configure Documents directory + echo "" echo "๐Ÿ“ Documents Directory:" if [[ -d "$default_docs" ]]; then - local reply=$(safe_read "Mount Documents directory ($default_docs)? (Y/n): " "Y") + local reply=$(safe_read "Mount Documents directory ($default_docs)? [Y/n]: " "Y") if [[ ! $reply =~ ^[Nn]$ ]]; then print_info "Documents directory will be mounted at /home/developer/Documents" else @@ -346,10 +345,9 @@ configure_directories() { fi fi - # Configure Projects directory echo "" echo "๐Ÿ’ป Projects Directory:" - local reply=$(safe_read "Do you want to mount a Projects directory? (Y/n): " "Y") + local reply=$(safe_read "Do you want to mount a Projects directory? [Y/n]: " "Y") if [[ ! $reply =~ ^[Nn]$ ]]; then local projects_dir=$(safe_read "Enter path to your projects directory [$default_projects]: " "$default_projects") @@ -368,10 +366,9 @@ configure_directories() { fi fi - # Configure additional directories echo "" echo "๐Ÿ“‚ Additional Directories:" - local reply=$(safe_read "Do you want to mount any additional directories? (y/N): " "N") + local reply=$(safe_read "Do you want to mount any additional directories? [y/N]: " "N") if [[ $reply =~ ^[Yy]$ ]]; then local counter=1 while true; do diff --git a/test-prompts.sh b/test-prompts.sh new file mode 100644 index 0000000..a3758ca --- /dev/null +++ b/test-prompts.sh @@ -0,0 +1,33 @@ +#!/bin/bash + +# Test script to verify prompt formatting consistency + +echo "Testing prompt formats..." +echo "" + +echo "=== Installation-style prompts ===" +printf "Enter your timezone [America/Mexico_City]: " +echo "America/New_York" + +printf "Mount Documents directory (/Users/user/Documents)? [Y/n]: " +echo "Y" + +printf "Do you want to mount a Projects directory? [Y/n]: " +echo "Y" + +printf "Enter path to your projects directory [/Users/user/Projects]: " +echo "/Users/user/Code" + +printf "Do you want to mount any additional directories? [y/N]: " +echo "N" + +echo "" +echo "=== Uninstallation-style prompts ===" +printf "Do you want to remove PATH modifications from shell config? [y/N]: " +echo "Y" + +printf "Are you sure you want to continue? [y/N]: " +echo "Y" + +echo "" +echo "All prompts use the same format: question on same line with clear brackets!" From 0c6c9018b2e1533e78fa9475f70456a5826f1769 Mon Sep 17 00:00:00 2001 From: Ricardo <31641216+manghidev@users.noreply.github.com> Date: Tue, 1 Jul 2025 09:15:20 -0600 Subject: [PATCH 07/20] refactor: remove obsolete test scripts for interactive prompts and sed commands --- VERSION | 2 +- test-interactive.sh | 157 -------------------------------------------- test-prompts.sh | 33 ---------- test-sed.sh | 36 ---------- 4 files changed, 1 insertion(+), 227 deletions(-) delete mode 100755 test-interactive.sh delete mode 100644 test-prompts.sh delete mode 100644 test-sed.sh diff --git a/VERSION b/VERSION index f0bb29e..3a3cd8c 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.3.0 +1.3.1 diff --git a/test-interactive.sh b/test-interactive.sh deleted file mode 100755 index 71dbaf3..0000000 --- a/test-interactive.sh +++ /dev/null @@ -1,157 +0,0 @@ -#!/bin/bash - -# Test Script - Test interactive configuration functions -# This script tests the interactive parts of the remote installer - -set -e - -# Colors for output -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -BLUE='\033[0;34m' -PURPLE='\033[0;35m' -CYAN='\033[0;36m' -NC='\033[0m' # No Color - -# Print functions -print_info() { - echo -e "${BLUE}[INFO]${NC} $1" -} - -print_success() { - echo -e "${GREEN}[SUCCESS]${NC} $1" -} - -print_step() { - echo -e "${PURPLE}[STEP]${NC} $1" -} - -# Test timezone configuration -test_configure_timezone() { - print_step "Testing timezone configuration..." - - # Detect system timezone - local system_tz="" - if command -v timedatectl >/dev/null 2>&1; then - system_tz=$(timedatectl show --property=Timezone --value 2>/dev/null || echo "") - elif [[ -f /etc/timezone ]]; then - system_tz=$(cat /etc/timezone 2>/dev/null || echo "") - elif [[ "$OSTYPE" == "darwin"* ]]; then - system_tz=$(ls -la /etc/localtime 2>/dev/null | sed 's/.*zoneinfo\///' || echo "") - fi - - # Default timezone if detection fails - local default_tz="${system_tz:-America/Mexico_City}" - - echo "Current system timezone detected: ${system_tz:-"Could not detect"}" - echo "Available timezone examples:" - echo " - America/New_York" - echo " - America/Los_Angeles" - echo " - America/Mexico_City" - echo " - Europe/London" - echo " - Europe/Madrid" - echo " - Asia/Tokyo" - echo "" - - printf "Enter your timezone [$default_tz]: " - read user_tz /home/developer/Projects" - else - print_info "Directory $projects_dir does not exist, but would be configured anyway" - fi - fi - - # Test additional directories - echo "" - echo "๐Ÿ“‚ Additional Directories:" - printf "Do you want to mount any additional directories? (y/N): " - read -r reply $container_path" - else - print_info "Directory $custom_dir does not exist, but would be configured anyway" - fi - done - fi -} - -echo -e "${CYAN}โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—${NC}" -echo -e "${CYAN}โ•‘ LazyVim Docker - Test โ•‘${NC}" -echo -e "${CYAN}โ•‘ Interactive Configuration Test โ•‘${NC}" -echo -e "${CYAN}โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•${NC}" -echo "" - -print_info "This script tests the interactive configuration functions" -print_info "Testing input compatibility for your shell: $(basename "$SHELL")" -echo "" - -test_configure_timezone -echo "" -test_configure_directories - -echo "" -print_success "โœ… All interactive functions work correctly!" -print_info "The configuration prompts are functioning properly in your shell." diff --git a/test-prompts.sh b/test-prompts.sh deleted file mode 100644 index a3758ca..0000000 --- a/test-prompts.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/bash - -# Test script to verify prompt formatting consistency - -echo "Testing prompt formats..." -echo "" - -echo "=== Installation-style prompts ===" -printf "Enter your timezone [America/Mexico_City]: " -echo "America/New_York" - -printf "Mount Documents directory (/Users/user/Documents)? [Y/n]: " -echo "Y" - -printf "Do you want to mount a Projects directory? [Y/n]: " -echo "Y" - -printf "Enter path to your projects directory [/Users/user/Projects]: " -echo "/Users/user/Code" - -printf "Do you want to mount any additional directories? [y/N]: " -echo "N" - -echo "" -echo "=== Uninstallation-style prompts ===" -printf "Do you want to remove PATH modifications from shell config? [y/N]: " -echo "Y" - -printf "Are you sure you want to continue? [y/N]: " -echo "Y" - -echo "" -echo "All prompts use the same format: question on same line with clear brackets!" diff --git a/test-sed.sh b/test-sed.sh deleted file mode 100644 index 3493d0b..0000000 --- a/test-sed.sh +++ /dev/null @@ -1,36 +0,0 @@ -#!/bin/bash - -# Test script to verify sed commands work with timezone values - -echo "Testing sed commands with timezone values..." - -# Create a test docker-compose.yml -cat > test-compose.yml << 'EOF' -services: - test: - environment: - - TIMEZONE: America/New_York - - TZ=America/New_York -EOF - -echo "Original file:" -cat test-compose.yml - -echo "" -echo "Testing with America/Chihuahua..." - -# Test with problematic timezone -timezone="America/Chihuahua" - -# Using pipe delimiters (safe) -sed -i.bak "s|TIMEZONE: .*|TIMEZONE: $timezone|" test-compose.yml -sed -i.bak2 "s|TZ=.*|TZ=$timezone|" test-compose.yml - -echo "After sed commands:" -cat test-compose.yml - -echo "" -echo "โœ… sed commands work correctly with pipe delimiters" - -# Cleanup -rm -f test-compose.yml test-compose.yml.bak test-compose.yml.bak2 From fa670573261389bc00b6777700786a870f525b0f Mon Sep 17 00:00:00 2001 From: Ricardo <31641216+manghidev@users.noreply.github.com> Date: Wed, 2 Jul 2025 09:18:23 -0600 Subject: [PATCH 08/20] refactor: refactor installation scripts: replace remote-install.sh with start.sh for automated setup with smart defaults --- Makefile | 6 +- README.md | 29 +- scripts/remote-install.sh | 494 ------------------ scripts/remote-uninstall.sh | 2 +- scripts/remote-update.sh | 2 +- .../{remote-install-simple.sh => start.sh} | 10 +- 6 files changed, 25 insertions(+), 518 deletions(-) delete mode 100755 scripts/remote-install.sh rename scripts/{remote-install-simple.sh => start.sh} (96%) mode change 100644 => 100755 diff --git a/Makefile b/Makefile index df259c5..1eab486 100644 --- a/Makefile +++ b/Makefile @@ -172,19 +172,19 @@ install-remote: @echo "$(BLUE)LazyVim Docker - Remote Installation$(NC)" @echo "" @echo "To install LazyVim Docker remotely (recommended):" - @echo "$(GREEN)curl -fsSL https://raw.githubusercontent.com/manghidev/lazyvim-docker/main/scripts/remote-install.sh | bash$(NC)" + @echo "$(GREEN)curl -fsSL https://raw.githubusercontent.com/manghidev/lazyvim-docker/main/scripts/start.sh | bash$(NC)" @echo "" @echo "This will:" @echo " โ€ข Download and install LazyVim Docker to ~/.local/share/lazyvim-docker" @echo " โ€ข Create global 'lazy' command" - @echo " โ€ข Build Docker environment" + @echo " โ€ข Build Docker environment with smart defaults" @echo " โ€ข No repository cloning required - everything is automated" remote-install: install-remote test-remote-scripts: @echo "$(BLUE)Testing remote installation scripts...$(NC)" - @bash -n scripts/remote-install.sh && echo "$(GREEN)โœ“ remote-install.sh syntax OK$(NC)" + @bash -n scripts/start.sh && echo "$(GREEN)โœ“ start.sh syntax OK$(NC)" @bash -n scripts/remote-uninstall.sh && echo "$(GREEN)โœ“ remote-uninstall.sh syntax OK$(NC)" @bash -n scripts/remote-update.sh && echo "$(GREEN)โœ“ remote-update.sh syntax OK$(NC)" @echo "$(GREEN)All remote scripts passed syntax check!$(NC)" diff --git a/README.md b/README.md index b631bff..e51140c 100644 --- a/README.md +++ b/README.md @@ -7,14 +7,15 @@ A professional Dockerized environment for LazyVim (advanced Neovim configuration ## ๐Ÿš€ Quick Start ### ๐ŸŒ Remote Installation (Recommended) -Install directly without cloning the repository - no manual setup needed: +Install directly without cloning the repository - automatic setup with smart defaults: ```bash -# One-line installation -curl -fsSL https://raw.githubusercontent.com/manghidev/lazyvim-docker/main/scripts/remote-install.sh | bash +# One-line installation with automatic configuration +curl -fsSL https://raw.githubusercontent.com/manghidev/lazyvim-docker/main/scripts/start.sh | bash # Then use from anywhere lazy enter # Enter LazyVim development environment +lazy configure # Customize your setup (optional) ``` ### ๐Ÿ“ฆ Traditional Installation @@ -83,11 +84,11 @@ make destroy # โš ๏ธ DANGEROUS: Removes everything LazyVim Docker provides three main remote scripts for easy management: ### ๐Ÿ“ฅ Installation Script -**`remote-install.sh`** - Complete setup in one command +**`start.sh`** - Automatic setup with smart defaults ```bash -# Full installation with Docker build -curl -fsSL https://raw.githubusercontent.com/manghidev/lazyvim-docker/main/scripts/remote-install.sh | bash +# Full installation with automatic configuration +curl -fsSL https://raw.githubusercontent.com/manghidev/lazyvim-docker/main/scripts/start.sh | bash ``` **What it does:** @@ -96,6 +97,7 @@ curl -fsSL https://raw.githubusercontent.com/manghidev/lazyvim-docker/main/scrip - โœ… Creates global `lazy` command in `~/.local/bin` - โœ… Adds `~/.local/bin` to your PATH automatically - โœ… Builds Docker environment (may take a few minutes) +- โœ… Uses smart defaults for timezone and directories - โœ… Creates shell configuration backups ### ๐Ÿ”„ Update Script @@ -140,8 +142,8 @@ curl -fsSL https://raw.githubusercontent.com/manghidev/lazyvim-docker/main/scrip ## ๐Ÿ”ฌ Script Details & Technical Info -### ๐Ÿ“ฅ remote-install.sh -**Purpose**: Complete LazyVim Docker setup without repository cloning +### ๐Ÿ“ฅ start.sh +**Purpose**: Complete LazyVim Docker setup with automatic configuration **Requirements Check:** - Docker (with compose support) @@ -220,7 +222,7 @@ curl -fsSL https://raw.githubusercontent.com/manghidev/lazyvim-docker/main/scrip ```bash # From your existing repo directory make destroy && cd .. && rm -rf lazyvim-docker -curl -fsSL https://raw.githubusercontent.com/manghidev/lazyvim-docker/main/scripts/remote-install.sh | bash +curl -fsSL https://raw.githubusercontent.com/manghidev/lazyvim-docker/main/scripts/start.sh | bash ``` **From Remote to Traditional:** @@ -235,8 +237,8 @@ git clone https://github.com/manghidev/lazyvim-docker.git && cd lazyvim-docker & ### Remote Installation Workflow (Recommended) ```bash -# 1. Install once (5-10 minutes) -curl -fsSL https://raw.githubusercontent.com/manghidev/lazyvim-docker/main/scripts/remote-install.sh | bash +# 1. Install once (5-10 minutes) - automatic setup +curl -fsSL https://raw.githubusercontent.com/manghidev/lazyvim-docker/main/scripts/start.sh | bash # 2. Daily usage from anywhere cd ~/Projects/my-project @@ -245,6 +247,7 @@ lazy enter # Start coding immediately # 3. Management commands lazy status # Check if running lazy stop # Stop when done +lazy configure # Customize setup (optional) lazy update # Update weekly/monthly ``` @@ -265,8 +268,6 @@ For detailed workflow and troubleshooting: **[๐Ÿ“– Container Lifecycle Guide](do --- -## ๐Ÿ”ง Advanced Configuration - ## ๐Ÿ”ง Configuration ### ๐ŸŽฏ Easy Configuration (Recommended) @@ -365,7 +366,7 @@ lazy build lazy update # Nuclear option -lazy uninstall && curl -fsSL https://raw.githubusercontent.com/manghidev/lazyvim-docker/main/scripts/remote-install.sh | bash +lazy uninstall && curl -fsSL https://raw.githubusercontent.com/manghidev/lazyvim-docker/main/scripts/start.sh | bash ``` --- diff --git a/scripts/remote-install.sh b/scripts/remote-install.sh deleted file mode 100755 index 7c6e2c8..0000000 --- a/scripts/remote-install.sh +++ /dev/null @@ -1,494 +0,0 @@ -#!/bin/bash - -# LazyVim Docker - Remote Installation Script -# This script downloads and installs LazyVim Docker environment directly from GitHub -# Usage: curl -fsSL https://raw.githubusercontent.com/USER/lazyvim-docker/main/scripts/remote-install.sh | bash - -set -e - -# Colors for output -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -BLUE='\033[0;34m' -PURPLE='\033[0;35m' -CYAN='\033[0;36m' -NC='\033[0m' # No Color - -# Configuration -REPO_URL="https://github.com/manghidev/lazyvim-docker" -REPO_NAME="lazyvim-docker" -INSTALL_DIR="$HOME/.local/share/lazyvim-docker" -BIN_DIR="$HOME/.local/bin" -TEMP_DIR="/tmp/lazyvim-docker-install" - -# Print functions -print_header() { - echo -e "${CYAN}โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—${NC}" - echo -e "${CYAN}โ•‘ LazyVim Docker - Remote Installer โ•‘${NC}" - echo -e "${CYAN}โ•‘ Easy One-Command Setup โ•‘${NC}" - echo -e "${CYAN}โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•${NC}" - echo "" -} - -print_info() { - echo -e "${BLUE}[INFO]${NC} $1" -} - -print_success() { - echo -e "${GREEN}[SUCCESS]${NC} $1" -} - -print_warning() { - echo -e "${YELLOW}[WARNING]${NC} $1" -} - -print_error() { - echo -e "${RED}[ERROR]${NC} $1" -} - -print_step() { - echo -e "${PURPLE}[STEP]${NC} $1" -} - -# Check if command exists -command_exists() { - command -v "$1" >/dev/null 2>&1 -} - -# Check system requirements -check_requirements() { - print_step "Checking system requirements..." - - local missing_deps=() - - if ! command_exists curl; then - missing_deps+=("curl") - fi - - if ! command_exists git; then - missing_deps+=("git") - fi - - if ! command_exists docker; then - missing_deps+=("docker") - fi - - if ! command_exists docker && ! docker compose version >/dev/null 2>&1; then - print_warning "Docker or Docker Compose not found." - if ! docker compose version >/dev/null 2>&1; then - missing_deps+=("docker") - fi - fi - - if [ ${#missing_deps[@]} -ne 0 ]; then - print_error "Missing required dependencies: ${missing_deps[*]}" - echo "" - print_info "Please install the missing dependencies and try again:" - echo "" - if [[ "$OSTYPE" == "darwin"* ]]; then - echo " brew install ${missing_deps[*]}" - elif [[ "$OSTYPE" == "linux"* ]]; then - echo " # Ubuntu/Debian:" - echo " sudo apt-get update && sudo apt-get install -y ${missing_deps[*]}" - echo "" - echo " # CentOS/RHEL:" - echo " sudo yum install -y ${missing_deps[*]}" - fi - echo "" - exit 1 - fi - - print_success "All requirements satisfied!" -} - -# Create necessary directories -create_directories() { - print_step "Creating installation directories..." - - mkdir -p "$INSTALL_DIR" - mkdir -p "$BIN_DIR" - mkdir -p "$TEMP_DIR" - - print_success "Directories created successfully" -} - -# Download the repository -download_repository() { - print_step "Downloading LazyVim Docker repository..." - - # Remove temp directory if it exists - rm -rf "$TEMP_DIR" - - # Clone the repository to temp directory - if git clone --depth 1 "$REPO_URL" "$TEMP_DIR" >/dev/null 2>&1; then - print_success "Repository downloaded successfully" - else - print_error "Failed to download repository from $REPO_URL" - exit 1 - fi -} - -# Install the application -install_application() { - print_step "Installing LazyVim Docker..." - - # Remove existing installation - if [ -d "$INSTALL_DIR" ]; then - print_info "Removing existing installation..." - rm -rf "$INSTALL_DIR" - fi - - # Move from temp to install directory - mv "$TEMP_DIR" "$INSTALL_DIR" - - # Make scripts executable - chmod +x "$INSTALL_DIR/scripts/"*.sh - chmod +x "$INSTALL_DIR/Makefile" - - print_success "Application installed to $INSTALL_DIR" -} - -# Setup PATH for local bin directory -setup_local_bin_path() { - local shell_config="$1" - local path_line="export PATH=\"\$HOME/.local/bin:\$PATH\"" - - # Create config file if it doesn't exist - touch "$shell_config" - - # Add to PATH if not already there - if ! grep -q "$HOME/.local/bin" "$shell_config" 2>/dev/null; then - echo "" >> "$shell_config" - echo "# LazyVim Docker - Add local bin to PATH" >> "$shell_config" - echo "$path_line" >> "$shell_config" - print_info "Added $HOME/.local/bin to PATH in $shell_config" - fi -} - -# Create global commands -create_global_commands() { - print_step "Installing global commands..." - - # Create bin directory if it doesn't exist - mkdir -p "$BIN_DIR" - - # Run the installer script from the project - cd "$INSTALL_DIR" - chmod +x ./scripts/install-global-commands.sh - if ./scripts/install-global-commands.sh; then - print_success "Global commands installed successfully" - else - print_error "Failed to install global commands" - exit 1 - fi - - # Ensure .local/bin is in PATH for both shells - setup_local_bin_path "$HOME/.bashrc" - setup_local_bin_path "$HOME/.zshrc" - - print_success "Global 'lazy' command is now available" -} - -# Check if we can do interactive input -can_interact() { - if [[ -t 0 ]]; then - # stdin is a terminal - return 0 - elif [[ -c /dev/tty ]] && exec < /dev/tty 2>/dev/null; then - # /dev/tty is available - return 0 - else - # No interactive input possible - return 1 - fi -} - -# Safe interactive read with consistent format -safe_read() { - local prompt="$1" - local default="$2" - local result="" - - if can_interact; then - printf "%s" "$prompt" - if [[ -c /dev/tty ]]; then - read result /dev/null || read result - else - read result - fi - echo "${result:-$default}" - else - print_warning "Running in non-interactive mode, using default: $default" - echo "$default" - fi -} - -# Configure timezone -configure_timezone() { - print_step "Configuring timezone..." - - # Detect system timezone - local system_tz="" - if command -v timedatectl >/dev/null 2>&1; then - system_tz=$(timedatectl show --property=Timezone --value 2>/dev/null || echo "") - elif [[ -f /etc/timezone ]]; then - system_tz=$(cat /etc/timezone 2>/dev/null || echo "") - elif [[ "$OSTYPE" == "darwin"* ]]; then - system_tz=$(ls -la /etc/localtime 2>/dev/null | sed 's/.*zoneinfo\///' || echo "") - fi - - # Default timezone if detection fails - local default_tz="${system_tz:-America/Mexico_City}" - - echo "๐ŸŒ Timezone Configuration:" - echo "Current system timezone detected: ${system_tz:-"Could not detect"}" - echo "Available timezone examples:" - echo " - America/New_York" - echo " - America/Los_Angeles" - echo " - America/Mexico_City" - echo " - Europe/London" - echo " - Europe/Madrid" - echo " - Asia/Tokyo" - echo "" - - local user_tz - if can_interact; then - user_tz=$(safe_read "Enter your timezone [$default_tz]: " "$default_tz") - else - user_tz="$default_tz" - print_info "Using detected/default timezone: $user_tz" - fi - - # Update timezone in docker-compose.yml - if [[ "$OSTYPE" == "darwin"* ]]; then - sed -i '' "s|TIMEZONE: .*|TIMEZONE: $user_tz|" docker-compose.yml - sed -i '' "s|TZ=.*|TZ=$user_tz|" docker-compose.yml - else - sed -i "s|TIMEZONE: .*|TIMEZONE: $user_tz|" docker-compose.yml - sed -i "s|TZ=.*|TZ=$user_tz|" docker-compose.yml - fi - - print_success "Timezone configured: $user_tz" -} - -# Configure directories -configure_directories() { - print_step "Configuring directories to mount..." - - # Detect OS - local os_type="" - local default_docs="$HOME/Documents" - local default_projects="" - - if [[ "$OSTYPE" == "darwin"* ]]; then - os_type="macOS" - default_projects="$HOME/Developer" - else - os_type="Linux" - default_projects="$HOME/Projects" - fi - - echo "Detected OS: $os_type" - echo "The container will mount directories so you can access your files inside the development environment." - echo "" - - if ! can_interact; then - print_info "Running in non-interactive mode - using smart defaults:" - print_info "โ€ข Documents: $default_docs (if exists)" - print_info "โ€ข Projects: $default_projects (if exists)" - - # Configure Documents automatically if exists - if [[ -d "$default_docs" ]]; then - print_success "Documents directory will be mounted: $default_docs" - else - # Comment out the Documents line - if [[ "$OSTYPE" == "darwin"* ]]; then - sed -i '' 's|^ - \$HOME/Documents:| # - \$HOME/Documents:|' docker-compose.yml - else - sed -i 's|^ - \$HOME/Documents:| # - \$HOME/Documents:|' docker-compose.yml - fi - print_info "Documents directory not found, mounting disabled" - fi - - # Configure Projects automatically if exists - if [[ -d "$default_projects" ]]; then - # Add projects directory to docker-compose.yml - if [[ "$OSTYPE" == "darwin"* ]]; then - sed -i '' "/\$HOME\/Documents:/a\\ - - $default_projects:/home/developer/Projects" docker-compose.yml - else - sed -i "/\$HOME\/Documents:/a\\ - - $default_projects:/home/developer/Projects" docker-compose.yml - fi - print_success "Projects directory added: $default_projects" - else - print_info "Projects directory not found: $default_projects" - fi - - return - fi - echo "" - echo "๐Ÿ“ Documents Directory:" - if [[ -d "$default_docs" ]]; then - local reply=$(safe_read "Mount Documents directory ($default_docs)? [Y/n]: " "Y") - if [[ ! $reply =~ ^[Nn]$ ]]; then - print_info "Documents directory will be mounted at /home/developer/Documents" - else - # Comment out the Documents line - if [[ "$OSTYPE" == "darwin"* ]]; then - sed -i '' 's|^ - \$HOME/Documents:| # - \$HOME/Documents:|' docker-compose.yml - else - sed -i 's|^ - \$HOME/Documents:| # - \$HOME/Documents:|' docker-compose.yml - fi - print_info "Documents directory mounting disabled" - fi - fi - - echo "" - echo "๐Ÿ’ป Projects Directory:" - local reply=$(safe_read "Do you want to mount a Projects directory? [Y/n]: " "Y") - if [[ ! $reply =~ ^[Nn]$ ]]; then - local projects_dir=$(safe_read "Enter path to your projects directory [$default_projects]: " "$default_projects") - - if [[ -d "$projects_dir" ]]; then - # Add projects directory to docker-compose.yml - if [[ "$OSTYPE" == "darwin"* ]]; then - sed -i '' "/\$HOME\/Documents:/a\\ - - $projects_dir:/home/developer/Projects" docker-compose.yml - else - sed -i "/\$HOME\/Documents:/a\\ - - $projects_dir:/home/developer/Projects" docker-compose.yml - fi - print_success "Projects directory added: $projects_dir -> /home/developer/Projects" - else - print_warning "Directory $projects_dir does not exist, you can add it later" - fi - fi - - echo "" - echo "๐Ÿ“‚ Additional Directories:" - local reply=$(safe_read "Do you want to mount any additional directories? [y/N]: " "N") - if [[ $reply =~ ^[Yy]$ ]]; then - local counter=1 - while true; do - echo "" - local custom_dir=$(safe_read "Enter directory path (or 'done' to finish): " "done") - if [[ "$custom_dir" == "done" ]]; then - break - fi - - if [[ -d "$custom_dir" ]]; then - local mount_name=$(basename "$custom_dir") - local container_path=$(safe_read "Mount as [/home/developer/$mount_name]: " "/home/developer/$mount_name") - container_path=${container_path:-"/home/developer/$mount_name"} - - # Add custom directory to docker-compose.yml - if [[ "$OSTYPE" == "darwin"* ]]; then - sed -i '' "/\$HOME\/Documents:/a\\ - - $custom_dir:$container_path" docker-compose.yml - else - sed -i "/\$HOME\/Documents:/a\\ - - $custom_dir:$container_path" docker-compose.yml - fi - print_success "Added: $custom_dir -> $container_path" - else - print_warning "Directory $custom_dir does not exist, skipping" - fi - - counter=$((counter + 1)) - if [[ $counter -gt 5 ]]; then - print_info "Maximum directories reached" - break - fi - done - fi - - print_success "Directory configuration completed" -} - -# Initial setup -initial_setup() { - print_step "Running initial setup..." - - cd "$INSTALL_DIR" - - echo "" - print_info "Let's configure your LazyVim Docker environment..." - echo "" - - # Ask for configuration - configure_timezone - echo "" - configure_directories - echo "" - - # Build the Docker environment - print_info "Building Docker environment (this may take a few minutes)..." - if make build; then - print_success "Docker environment built successfully" - else - print_warning "Docker build failed, but installation completed. You can run 'lazy build' later." - fi -} - -# Cleanup -cleanup() { - print_step "Cleaning up temporary files..." - rm -rf "$TEMP_DIR" - print_success "Cleanup completed" -} - -# Handle stdin for piped execution -handle_stdin() { - # If we're being piped into, redirect stdin to terminal - if [[ ! -t 0 ]]; then - exec < /dev/tty 2>/dev/null || exec < /dev/stdin - fi -} - -# Main installation process -main() { - # Handle stdin redirection first - handle_stdin - - print_header - - print_info "Starting LazyVim Docker remote installation..." - print_info "Installation directory: $INSTALL_DIR" - print_info "Binary directory: $BIN_DIR" - echo "" - - check_requirements - create_directories - download_repository - install_application - create_global_commands - initial_setup - cleanup - - echo "" - print_success "๐ŸŽ‰ LazyVim Docker installed successfully!" - echo "" - print_info "Usage:" - echo " ${GREEN}lazy enter${NC} # Enter LazyVim development environment" - echo " ${GREEN}lazy start${NC} # Start the container" - echo " ${GREEN}lazy stop${NC} # Stop the container" - echo " ${GREEN}lazy status${NC} # Check container status" - echo " ${GREEN}lazy configure${NC} # Reconfigure directories and timezone" - echo " ${GREEN}lazy update${NC} # Update to latest version" - echo " ${GREEN}lazy uninstall${NC} # Uninstall everything" - echo " ${GREEN}lazy help${NC} # Show all available commands" - echo "" - print_info "To get started:" - echo " 1. Restart your terminal or run: ${YELLOW}source ~/.zshrc${NC} (or ~/.bashrc)" - echo " 2. Run: ${GREEN}lazy enter${NC}" - echo "" - print_info "To reconfigure directories or timezone later:" - echo " Run: ${GREEN}lazy configure${NC}" - echo "" - print_info "Happy coding! ๐Ÿš€" -} - -# Run main function -main "$@" diff --git a/scripts/remote-uninstall.sh b/scripts/remote-uninstall.sh index 248e52b..b305226 100755 --- a/scripts/remote-uninstall.sh +++ b/scripts/remote-uninstall.sh @@ -225,7 +225,7 @@ main() { print_info "Thank you for using LazyVim Docker! ๐Ÿš€" echo "" print_info "To reinstall later, run:" - echo " ${GREEN}curl -fsSL https://raw.githubusercontent.com/manghidev/lazyvim-docker/main/scripts/remote-install.sh | bash${NC}" + echo " ${GREEN}curl -fsSL https://raw.githubusercontent.com/manghidev/lazyvim-docker/main/scripts/start.sh | bash${NC}" echo "" } diff --git a/scripts/remote-update.sh b/scripts/remote-update.sh index b0a259e..b03aa24 100755 --- a/scripts/remote-update.sh +++ b/scripts/remote-update.sh @@ -53,7 +53,7 @@ check_installation() { if [ ! -d "$INSTALL_DIR" ]; then print_error "LazyVim Docker installation not found at: $INSTALL_DIR" print_info "Please install first:" - echo " curl -fsSL https://raw.githubusercontent.com/manghidev/lazyvim-docker/main/scripts/remote-install.sh | bash" + echo " curl -fsSL https://raw.githubusercontent.com/manghidev/lazyvim-docker/main/scripts/start.sh | bash" exit 1 fi } diff --git a/scripts/remote-install-simple.sh b/scripts/start.sh old mode 100644 new mode 100755 similarity index 96% rename from scripts/remote-install-simple.sh rename to scripts/start.sh index 7535fcb..bb3b21e --- a/scripts/remote-install-simple.sh +++ b/scripts/start.sh @@ -1,8 +1,8 @@ #!/bin/bash -# LazyVim Docker - Simple Remote Installation Script -# This version uses smart defaults and skips interactive configuration -# Perfect for automated installations or when interactive input fails +# LazyVim Docker - One-Command Setup +# Automatic installation with smart defaults - no questions asked! +# Usage: curl -fsSL https://raw.githubusercontent.com/USER/lazyvim-docker/main/scripts/start.sh | bash set -e @@ -26,8 +26,8 @@ BRANCH="${LAZYVIM_BRANCH:-develop}" # Print functions print_header() { echo -e "${CYAN}โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—${NC}" - echo -e "${CYAN}โ•‘ LazyVim Docker - Simple Installer โ•‘${NC}" - echo -e "${CYAN}โ•‘ Smart Defaults, Zero Input โ•‘${NC}" + echo -e "${CYAN}โ•‘ LazyVim Docker - Quick Start โ•‘${NC}" + echo -e "${CYAN}โ•‘ One Command, Instant Development โ•‘${NC}" echo -e "${CYAN}โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•${NC}" echo "" } From 6b756914a93d515e5d7bb540ddfedd753ef09373 Mon Sep 17 00:00:00 2001 From: Ricardo <31641216+manghidev@users.noreply.github.com> Date: Wed, 2 Jul 2025 09:45:23 -0600 Subject: [PATCH 09/20] feat: add shell detection and terminal restart functionality to installation and uninstallation scripts --- scripts/remote-uninstall.sh | 48 +++++++++++++++++++++++++++++++++ scripts/start.sh | 53 ++++++++++++++++++++++++++++++++++--- 2 files changed, 97 insertions(+), 4 deletions(-) diff --git a/scripts/remote-uninstall.sh b/scripts/remote-uninstall.sh index b305226..e3be9c8 100755 --- a/scripts/remote-uninstall.sh +++ b/scripts/remote-uninstall.sh @@ -46,6 +46,51 @@ print_step() { echo -e "${PURPLE}[STEP]${NC} $1" } +# Detect current shell and restart terminal +restart_terminal() { + print_step "Restarting terminal to apply changes..." + + # Detect current shell - prioritize SHELL environment variable for user's preference + local current_shell="" + if [ -n "$SHELL" ]; then + case "$SHELL" in + */zsh) + current_shell="zsh" + ;; + */bash) + current_shell="bash" + ;; + *) + # Check if we're currently in a specific shell + if [ -n "$ZSH_VERSION" ]; then + current_shell="zsh" + elif [ -n "$BASH_VERSION" ]; then + current_shell="bash" + else + # Default to bash if unable to detect + current_shell="bash" + fi + ;; + esac + else + # Fallback if SHELL is not set + if [ -n "$ZSH_VERSION" ]; then + current_shell="zsh" + elif [ -n "$BASH_VERSION" ]; then + current_shell="bash" + else + current_shell="bash" + fi + fi + + print_info "Detected shell: $current_shell" + print_info "Restarting terminal to clean up environment..." + echo "" + + # Execute the shell to restart + exec "$current_shell" +} + # Stop and remove Docker containers cleanup_docker() { print_step "Cleaning up Docker containers and images..." @@ -227,6 +272,9 @@ main() { print_info "To reinstall later, run:" echo " ${GREEN}curl -fsSL https://raw.githubusercontent.com/manghidev/lazyvim-docker/main/scripts/start.sh | bash${NC}" echo "" + + # Restart terminal to clean up environment + restart_terminal } # Run main function diff --git a/scripts/start.sh b/scripts/start.sh index bb3b21e..b355285 100755 --- a/scripts/start.sh +++ b/scripts/start.sh @@ -52,6 +52,51 @@ print_step() { echo -e "${PURPLE}[STEP]${NC} $1" } +# Detect current shell and restart terminal +restart_terminal() { + print_step "Restarting terminal to apply changes..." + + # Detect current shell - prioritize SHELL environment variable for user's preference + local current_shell="" + if [ -n "$SHELL" ]; then + case "$SHELL" in + */zsh) + current_shell="zsh" + ;; + */bash) + current_shell="bash" + ;; + *) + # Check if we're currently in a specific shell + if [ -n "$ZSH_VERSION" ]; then + current_shell="zsh" + elif [ -n "$BASH_VERSION" ]; then + current_shell="bash" + else + # Default to bash if unable to detect + current_shell="bash" + fi + ;; + esac + else + # Fallback if SHELL is not set + if [ -n "$ZSH_VERSION" ]; then + current_shell="zsh" + elif [ -n "$BASH_VERSION" ]; then + current_shell="bash" + else + current_shell="bash" + fi + fi + + print_info "Detected shell: $current_shell" + print_info "Restarting terminal to make 'lazy' commands available..." + echo "" + + # Execute the shell to restart + exec "$current_shell" +} + # Check if command exists command_exists() { command -v "$1" >/dev/null 2>&1 @@ -312,14 +357,14 @@ main() { echo " ${GREEN}lazy uninstall${NC} # Uninstall everything" echo " ${GREEN}lazy help${NC} # Show all available commands" echo "" - print_info "To get started:" - echo " 1. Restart your terminal or run: ${YELLOW}source ~/.zshrc${NC} (or ~/.bashrc)" - echo " 2. Run: ${GREEN}lazy enter${NC}" - echo "" print_info "To customize configuration later:" echo " Run: ${GREEN}lazy configure${NC}" echo "" print_info "Happy coding! ๐Ÿš€" + echo "" + + # Restart terminal to make commands available immediately + restart_terminal } # Run main function From 510d48b23c328a4ac20a40a85a86a17daf4544c7 Mon Sep 17 00:00:00 2001 From: Ricardo <31641216+manghidev@users.noreply.github.com> Date: Wed, 2 Jul 2025 10:26:05 -0600 Subject: [PATCH 10/20] feat: enhance terminal restart functionality with user-friendly options and helper scripts --- scripts/remote-uninstall.sh | 74 ++++++++++++++++++++--------------- scripts/start.sh | 77 ++++++++++++++++++++++--------------- 2 files changed, 89 insertions(+), 62 deletions(-) diff --git a/scripts/remote-uninstall.sh b/scripts/remote-uninstall.sh index e3be9c8..12307c9 100755 --- a/scripts/remote-uninstall.sh +++ b/scripts/remote-uninstall.sh @@ -46,49 +46,61 @@ print_step() { echo -e "${PURPLE}[STEP]${NC} $1" } -# Detect current shell and restart terminal +# Smart terminal restart for clean environment restart_terminal() { - print_step "Restarting terminal to apply changes..." + print_step "Setting up terminal cleanup..." - # Detect current shell - prioritize SHELL environment variable for user's preference + # Detect current shell local current_shell="" if [ -n "$SHELL" ]; then case "$SHELL" in - */zsh) - current_shell="zsh" - ;; - */bash) - current_shell="bash" - ;; - *) - # Check if we're currently in a specific shell - if [ -n "$ZSH_VERSION" ]; then - current_shell="zsh" - elif [ -n "$BASH_VERSION" ]; then - current_shell="bash" - else - # Default to bash if unable to detect - current_shell="bash" - fi - ;; + */zsh) current_shell="zsh" ;; + */bash) current_shell="bash" ;; + *) current_shell="bash" ;; esac else - # Fallback if SHELL is not set - if [ -n "$ZSH_VERSION" ]; then - current_shell="zsh" - elif [ -n "$BASH_VERSION" ]; then - current_shell="bash" - else - current_shell="bash" - fi + current_shell="bash" fi print_info "Detected shell: $current_shell" - print_info "Restarting terminal to clean up environment..." + + # Create a helper script for easy restart + local helper_script="/tmp/lazyvim_cleanup_terminal.sh" + cat > "$helper_script" << 'EOF' +#!/bin/bash +echo "๐Ÿงน Restarting terminal to complete LazyVim Docker cleanup..." +echo "" +EOF + echo "exec $current_shell" >> "$helper_script" + chmod +x "$helper_script" + + echo "" + print_warning "๐Ÿงน To complete cleanup and remove any traces:" + echo "" + echo " ${GREEN}Option 1 (Easiest):${NC}" + echo " ${GREEN}$helper_script${NC}" + echo "" + echo " ${GREEN}Option 2 (Manual):${NC}" + echo " ${GREEN}exec $current_shell${NC}" echo "" - # Execute the shell to restart - exec "$current_shell" + # Try to detect if we can restart directly + if [[ -t 0 ]] && [[ -t 1 ]] && [[ $- == *i* ]]; then + print_info "โœจ Auto-cleanup available!" + local choice + printf "Press ENTER to restart now, or 'n' to skip cleanup: " + read -r choice + + if [[ "$choice" != "n" ]] && [[ "$choice" != "N" ]]; then + print_info "Restarting terminal for clean environment..." + exec "$current_shell" + else + print_info "Cleanup skipped - environment may show command traces" + fi + else + print_info "๏ฟฝ Copy and paste the first command to clean your terminal" + print_info "This ensures no traces of 'lazy' commands remain" + fi } # Stop and remove Docker containers diff --git a/scripts/start.sh b/scripts/start.sh index b355285..11a50db 100755 --- a/scripts/start.sh +++ b/scripts/start.sh @@ -52,49 +52,64 @@ print_step() { echo -e "${PURPLE}[STEP]${NC} $1" } -# Detect current shell and restart terminal +# Smart terminal restart with helper script restart_terminal() { - print_step "Restarting terminal to apply changes..." + print_step "Setting up terminal restart..." - # Detect current shell - prioritize SHELL environment variable for user's preference + # Detect current shell local current_shell="" if [ -n "$SHELL" ]; then case "$SHELL" in - */zsh) - current_shell="zsh" - ;; - */bash) - current_shell="bash" - ;; - *) - # Check if we're currently in a specific shell - if [ -n "$ZSH_VERSION" ]; then - current_shell="zsh" - elif [ -n "$BASH_VERSION" ]; then - current_shell="bash" - else - # Default to bash if unable to detect - current_shell="bash" - fi - ;; + */zsh) current_shell="zsh" ;; + */bash) current_shell="bash" ;; + *) current_shell="bash" ;; esac else - # Fallback if SHELL is not set - if [ -n "$ZSH_VERSION" ]; then - current_shell="zsh" - elif [ -n "$BASH_VERSION" ]; then - current_shell="bash" - else - current_shell="bash" - fi + current_shell="bash" fi print_info "Detected shell: $current_shell" - print_info "Restarting terminal to make 'lazy' commands available..." + + # Create a helper script for easy restart + local helper_script="/tmp/lazyvim_restart_terminal.sh" + cat > "$helper_script" << 'EOF' +#!/bin/bash +echo "๐Ÿ”„ Restarting terminal to activate LazyVim Docker commands..." +echo "" +EOF + echo "exec $current_shell" >> "$helper_script" + chmod +x "$helper_script" + + echo "" + print_warning "๐Ÿ”„ To activate 'lazy' commands, choose the EASIEST option:" + echo "" + echo " ${GREEN}Option 1 (Easiest):${NC}" + echo " ${GREEN}$helper_script${NC}" + echo "" + echo " ${GREEN}Option 2 (Manual):${NC}" + echo " ${GREEN}exec $current_shell${NC}" + echo "" + echo " ${GREEN}Option 3 (Alternative):${NC}" + echo " ${GREEN}source ~/.${current_shell}rc${NC}" echo "" - # Execute the shell to restart - exec "$current_shell" + # Try to detect if we can restart directly + if [[ -t 0 ]] && [[ -t 1 ]] && [[ $- == *i* ]]; then + print_info "โœจ Auto-restart available!" + local choice + printf "Press ENTER to restart now, or 'n' to do it manually: " + read -r choice + + if [[ "$choice" != "n" ]] && [[ "$choice" != "N" ]]; then + print_info "Restarting terminal..." + exec "$current_shell" + else + print_info "Manual restart chosen - use the commands above" + fi + else + print_info "๐Ÿ’ก Copy and paste the first command to restart your terminal" + print_info "Then run: ${GREEN}lazy enter${NC}" + fi } # Check if command exists From 135f6a2d9023a2ab3afa379ada0cf72cabd785f3 Mon Sep 17 00:00:00 2001 From: Ricardo <31641216+manghidev@users.noreply.github.com> Date: Wed, 2 Jul 2025 11:09:03 -0600 Subject: [PATCH 11/20] feat: enhance configure.sh with improved directory management and user preferences handling --- .lazyvim-docker-config | 6 + scripts/configure.sh | 664 ++++++++++++++++++++++++++++------------- 2 files changed, 467 insertions(+), 203 deletions(-) create mode 100644 .lazyvim-docker-config diff --git a/.lazyvim-docker-config b/.lazyvim-docker-config new file mode 100644 index 0000000..173c3b0 --- /dev/null +++ b/.lazyvim-docker-config @@ -0,0 +1,6 @@ +# LazyVim Docker Configuration - Auto-generated +# Last updated: Wed Jul 2 11:06:39 CST 2025 +DOCUMENTS_DECISION="no" +PROJECTS_DECISION="no" +PROJECTS_PATH="" +LAST_TIMEZONE="America/Mexico_City" diff --git a/scripts/configure.sh b/scripts/configure.sh index ac5a6b6..53785fe 100755 --- a/scripts/configure.sh +++ b/scripts/configure.sh @@ -1,7 +1,12 @@ #!/bin/bash -# LazyVim Docker - Configuration Script -# This script helps reconfigure directories and timezone +# LazyVim Docker - Enhanced Configuration Script v2.0 +# Features: +# - Prevents duplicate directory mounts +# - Allows easy unmounting of directories from menu +# - Remembers user decisions (won't ask again for Documents if already configured) +# - Shows clear numbered list of mounted directories +# - Persistent preferences management set -e @@ -11,36 +16,231 @@ GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' CYAN='\033[0;36m' +PURPLE='\033[0;35m' +GRAY='\033[0;37m' NC='\033[0m' +# Configuration file to store user preferences +CONFIG_FILE=".lazyvim-docker-config" + # Functions log_info() { - echo -e "${BLUE}[INFO]${NC} $1" + echo -e "${BLUE}โ„น๏ธ ${NC} $1" } log_success() { - echo -e "${GREEN}[SUCCESS]${NC} $1" + echo -e "${GREEN}โœ… ${NC} $1" } log_warning() { - echo -e "${YELLOW}[WARNING]${NC} $1" + echo -e "${YELLOW}โš ๏ธ ${NC} $1" } log_error() { - echo -e "${RED}[ERROR]${NC} $1" + echo -e "${RED}โŒ ${NC} $1" +} + +log_step() { + echo -e "${PURPLE}๐Ÿ”ง ${NC} $1" } print_header() { echo -e "${CYAN}โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—${NC}" - echo -e "${CYAN}โ•‘ LazyVim Docker - Configuration โ•‘${NC}" - echo -e "${CYAN}โ•‘ Reconfigure Directories & Timezone โ•‘${NC}" + echo -e "${CYAN}โ•‘ LazyVim Docker - Smart Configuration Tool โ•‘${NC}" + echo -e "${CYAN}โ•‘ Improved Directory & Timezone Manager v2.0 โ•‘${NC}" echo -e "${CYAN}โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•${NC}" echo "" } -# Configure timezone +# Load user preferences +load_config() { + if [[ -f "$CONFIG_FILE" ]]; then + source "$CONFIG_FILE" + log_info "Loaded previous configuration" + else + log_info "First time configuration" + fi +} + +# Save user preferences +save_config() { + cat > "$CONFIG_FILE" << EOF +# LazyVim Docker Configuration - Auto-generated +# Last updated: $(date) +DOCUMENTS_DECISION="${DOCUMENTS_DECISION:-}" +PROJECTS_DECISION="${PROJECTS_DECISION:-}" +PROJECTS_PATH="${PROJECTS_PATH:-}" +LAST_TIMEZONE="${LAST_TIMEZONE:-}" +EOF + log_info "Configuration saved to $CONFIG_FILE" +} + +# Check if a directory mount already exists in docker-compose.yml +is_mount_exists() { + local host_path="$1" + + # Normalize path for comparison (resolve $HOME, relative paths, etc.) + local normalized_path="$host_path" + if [[ "$host_path" =~ ^\$HOME ]]; then + normalized_path="${host_path/\$HOME/$HOME}" + fi + + # Check if mount exists (non-commented line) + if grep -v "^[[:space:]]*#" docker-compose.yml | grep -q "- $host_path:" || \ + grep -v "^[[:space:]]*#" docker-compose.yml | grep -q "- $normalized_path:"; then + return 0 # Mount exists + else + return 1 # Mount doesn't exist + fi +} + +# Get all current mounts in a structured way +get_current_mounts() { + local show_numbers="${1:-false}" + local counter=1 + local mounts_found=false + local mounts_data=() + + echo -e "${CYAN}๐Ÿ“ Current Directory Mounts:${NC}" + echo "โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”" + + # Parse docker-compose.yml for volume mounts + while IFS= read -r line; do + if [[ "$line" =~ ^[[:space:]]*-[[:space:]]+([^:]+):([^:]+)$ ]]; then + local host_path="${BASH_REMATCH[1]}" + local container_path="${BASH_REMATCH[2]}" + + # Skip system mounts (cache, npm, etc.) + if [[ "$container_path" =~ (cache|npm|pip|yarn|\.dotfiles|\.ssh|config/nvim) ]]; then + continue + fi + + # Expand environment variables for display + local display_host_path="$host_path" + if [[ "$host_path" =~ ^\$HOME ]]; then + display_host_path="${host_path/\$HOME/$HOME}" + fi + + # Store mount data for potential removal + mounts_data+=("$host_path:$container_path") + + # Show numbered list if requested + if [[ "$show_numbers" == "true" ]]; then + printf "${YELLOW}%2d.${NC} " "$counter" + else + printf " ${PURPLE}โ€ข${NC} " + fi + + printf "${GREEN}Host:${NC} %s\n" "$display_host_path" + printf " ${CYAN}โ†’${NC} Container: %s\n" "$container_path" + + # Check if directory exists + if [[ -d "$display_host_path" ]]; then + printf " ${BLUE}Status:${NC} ${GREEN}โœ… Exists${NC}\n" + else + printf " ${BLUE}Status:${NC} ${RED}โŒ Missing${NC}\n" + fi + echo "" + + counter=$((counter + 1)) + mounts_found=true + fi + done < <(grep -v "^[[:space:]]*#" docker-compose.yml | grep -E "^\s*-\s+.*:.*$") + + if [[ "$mounts_found" != "true" ]]; then + echo " ${GRAY}No custom directory mounts configured${NC}" + echo "" + fi + + echo "โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”" + + # Export mounts data for removal function + export CURRENT_MOUNTS_DATA="${mounts_data[*]}" + return $((counter - 1)) # Return total count +} + +# Add a directory mount (prevents duplicates) +add_directory_mount() { + local host_path="$1" + local container_path="$2" + + # Check if mount already exists + if is_mount_exists "$host_path"; then + log_warning "Mount already exists: $host_path" + return 1 + fi + + # Check if directory exists + if [[ ! -d "$host_path" ]]; then + log_error "Directory does not exist: $host_path" + return 1 + fi + + # Add mount after the Documents line or at the end of volumes section + if grep -q "Documents:" docker-compose.yml; then + # Add after Documents line + if [[ "$OSTYPE" == "darwin"* ]]; then + sed -i '' "/\$HOME\/Documents:/a\\ + - $host_path:$container_path" docker-compose.yml + else + sed -i "/\$HOME\/Documents:/a\\ + - $host_path:$container_path" docker-compose.yml + fi + else + # Find volumes section and add there + if [[ "$OSTYPE" == "darwin"* ]]; then + sed -i '' "/volumes:/a\\ + - $host_path:$container_path" docker-compose.yml + else + sed -i "/volumes:/a\\ + - $host_path:$container_path" docker-compose.yml + fi + fi + + log_success "Added mount: $host_path โ†’ $container_path" + return 0 +} + +# Remove a directory mount by line number +remove_directory_mount() { + local selection="$1" + + # Get current mounts data + get_current_mounts "false" > /dev/null + + if [[ -z "$CURRENT_MOUNTS_DATA" ]]; then + log_warning "No mounts available to remove" + return 1 + fi + + # Convert space-separated data to array + IFS=' ' read -ra mounts_array <<< "$CURRENT_MOUNTS_DATA" + + # Validate selection + if [[ ! "$selection" =~ ^[0-9]+$ ]] || [[ "$selection" -lt 1 ]] || [[ "$selection" -gt "${#mounts_array[@]}" ]]; then + log_error "Invalid selection: $selection" + return 1 + fi + + # Get the mount to remove (1-indexed to 0-indexed) + local mount_to_remove="${mounts_array[$((selection - 1))]}" + local host_path="${mount_to_remove%:*}" + local container_path="${mount_to_remove#*:}" + + # Remove the mount line from docker-compose.yml + if [[ "$OSTYPE" == "darwin"* ]]; then + sed -i '' "\|^[[:space:]]*- $host_path:$container_path|d" docker-compose.yml + else + sed -i "\|^[[:space:]]*- $host_path:$container_path|d" docker-compose.yml + fi + + log_success "Removed mount: $host_path โ†’ $container_path" + return 0 +} + +# Configure timezone with memory configure_timezone() { - log_info "Configuring timezone..." + log_step "Configuring timezone..." # Detect system timezone local system_tz="" @@ -53,257 +253,315 @@ configure_timezone() { fi # Get current timezone from docker-compose.yml - local current_tz=$(grep "TIMEZONE:" docker-compose.yml | awk '{print $2}' || echo "") + local current_tz=$(grep "TIMEZONE:" docker-compose.yml | awk '{print $2}' 2>/dev/null || echo "") + local default_tz="${system_tz:-America/Mexico_City}" - # Default timezone if detection fails - local default_tz="${system_tz:-${current_tz:-America/Mexico_City}}" - - echo "Current system timezone: ${system_tz:-"Could not detect"}" - echo "Current container timezone: ${current_tz:-"Not set"}" + echo "๐ŸŒ Timezone Configuration:" + echo " Current in container: ${current_tz:-"Not set"}" + echo " System timezone: ${system_tz:-"Could not detect"}" echo "" + + # If we have a previous timezone decision and it matches current, skip + if [[ -n "$LAST_TIMEZONE" ]] && [[ "$LAST_TIMEZONE" == "$current_tz" ]]; then + log_info "Timezone already configured: $current_tz" + return 0 + fi + echo "Available timezone examples:" - echo " - America/New_York (EST/EDT)" - echo " - America/Los_Angeles (PST/PDT)" - echo " - America/Chicago (CST/CDT)" - echo " - America/Mexico_City (CST/CDT)" - echo " - Europe/London (GMT/BST)" - echo " - Europe/Madrid (CET/CEST)" - echo " - Europe/Paris (CET/CEST)" - echo " - Asia/Tokyo (JST)" - echo " - Asia/Shanghai (CST)" + echo " - America/New_York" + echo " - America/Los_Angeles" + echo " - America/Mexico_City" + echo " - Europe/London" + echo " - Europe/Madrid" + echo " - Asia/Tokyo" echo "" - read -p "Enter your timezone [$default_tz]: " user_tz - user_tz=${user_tz:-$default_tz} + read -p "Enter timezone [$default_tz]: " timezone + timezone=${timezone:-$default_tz} - # Update timezone in docker-compose.yml + # Update docker-compose.yml if [[ "$OSTYPE" == "darwin"* ]]; then - sed -i '' "s/TIMEZONE: .*/TIMEZONE: $user_tz/" docker-compose.yml - sed -i '' "s/TZ=.*/TZ=$user_tz/" docker-compose.yml + sed -i '' "s|TIMEZONE:.*|TIMEZONE: $timezone|" docker-compose.yml else - sed -i "s/TIMEZONE: .*/TIMEZONE: $user_tz/" docker-compose.yml - sed -i "s/TZ=.*/TZ=$user_tz/" docker-compose.yml + sed -i "s|TIMEZONE:.*|TIMEZONE: $timezone|" docker-compose.yml fi - log_success "Timezone configured: $user_tz" + LAST_TIMEZONE="$timezone" + log_success "Timezone set to: $timezone" } -# Configure directories -configure_directories() { - log_info "Configuring directories to mount..." - - # Detect OS - local os_type="" +# Configure Documents directory with smart state +configure_documents_directory() { local default_docs="$HOME/Documents" - local default_projects="" - if [[ "$OSTYPE" == "darwin"* ]]; then - os_type="macOS" - default_projects="$HOME/Developer" - else - os_type="Linux" - default_projects="$HOME/Projects" + echo "๐Ÿ“„ Documents Directory Configuration:" + + # Check if Documents directory exists + if [[ ! -d "$default_docs" ]]; then + log_warning "Documents directory not found: $default_docs" + return 0 fi - echo "Detected OS: $os_type" - echo "The container will mount directories so you can access your files inside the development environment." - echo "" + # Check current state in docker-compose.yml + local is_enabled=$(grep -v "^[[:space:]]*#" docker-compose.yml | grep -q "\$HOME/Documents:" && echo "yes" || echo "no") - # Show current mounts - echo "Current volume mounts in docker-compose.yml:" - grep -E "^\s*-\s+.*:.*$" docker-compose.yml | grep -v "cache\|npm\|pip" | sed 's/^/ /' + # If we have a previous decision and current state matches, skip asking + if [[ -n "$DOCUMENTS_DECISION" ]]; then + if [[ "$DOCUMENTS_DECISION" == "yes" ]] && [[ "$is_enabled" == "yes" ]]; then + log_info "Documents directory already enabled: $default_docs" + return 0 + elif [[ "$DOCUMENTS_DECISION" == "no" ]] && [[ "$is_enabled" == "no" ]]; then + log_info "Documents directory already disabled (user preference)" + return 0 + fi + fi + + echo " Path: $default_docs" + echo " Status: $([ "$is_enabled" == "yes" ] && echo "โœ… Enabled" || echo "โŒ Disabled")" echo "" - # Configure Documents directory - echo "๐Ÿ“ Documents Directory:" - if [[ -d "$default_docs" ]]; then - read -p "Mount Documents directory ($default_docs)? (Y/n): " -n 1 -r - echo - if [[ ! $REPLY =~ ^[Nn]$ ]]; then - # Ensure Documents is enabled + local reply + read -p "Mount Documents directory? [Y/n]: " reply + + case "$reply" in + [nN][oO]|[nN]) + # Disable Documents mounting if [[ "$OSTYPE" == "darwin"* ]]; then - sed -i '' 's|^ # - \$HOME/Documents:| - \$HOME/Documents:|' docker-compose.yml + sed -i '' 's|^[[:space:]]*- \$HOME/Documents:| # - \$HOME/Documents:|' docker-compose.yml else - sed -i 's|^ # - \$HOME/Documents:| - \$HOME/Documents:|' docker-compose.yml + sed -i 's|^[[:space:]]*- \$HOME/Documents:| # - \$HOME/Documents:|' docker-compose.yml fi - log_info "Documents directory will be mounted at /home/developer/Documents" - else - # Comment out the Documents line + DOCUMENTS_DECISION="no" + log_success "Documents directory mounting disabled" + ;; + *) + # Enable Documents mounting if [[ "$OSTYPE" == "darwin"* ]]; then - sed -i '' 's|^ - \$HOME/Documents:| # - \$HOME/Documents:|' docker-compose.yml + sed -i '' 's|^[[:space:]]*#[[:space:]]*- \$HOME/Documents:| - \$HOME/Documents:|' docker-compose.yml else - sed -i 's|^ - \$HOME/Documents:| # - \$HOME/Documents:|' docker-compose.yml + sed -i 's|^[[:space:]]*#[[:space:]]*- \$HOME/Documents:| - \$HOME/Documents:|' docker-compose.yml fi - log_info "Documents directory mounting disabled" - fi + DOCUMENTS_DECISION="yes" + log_success "Documents directory mounting enabled" + ;; + esac +} + +# Configure Projects directory with smart state +configure_projects_directory() { + local default_projects="" + + if [[ "$OSTYPE" == "darwin"* ]]; then + default_projects="$HOME/Developer" + else + default_projects="$HOME/Projects" fi - # Configure Projects directory echo "" - echo "๐Ÿ’ป Projects Directory:" - local has_projects=$(grep -c "Projects:/home/developer/Projects" docker-compose.yml || echo "0") - - if [[ $has_projects -gt 0 ]]; then - local current_projects=$(grep "Projects:/home/developer/Projects" docker-compose.yml | sed 's/.*- //' | sed 's/:.*//') - echo "Current Projects directory: $current_projects" - read -p "Keep current Projects directory? (Y/n): " -n 1 -r - echo - if [[ $REPLY =~ ^[Nn]$ ]]; then - # Remove current projects line - if [[ "$OSTYPE" == "darwin"* ]]; then - sed -i '' '/Projects:\/home\/developer\/Projects/d' docker-compose.yml - else - sed -i '/Projects:\/home\/developer\/Projects/d' docker-compose.yml - fi - has_projects=0 + echo "๐Ÿ’ป Projects Directory Configuration:" + + # Get current Projects mount if exists + local current_projects=$(grep -v "^[[:space:]]*#" docker-compose.yml | grep "Projects:/home/developer/Projects" | sed 's/.*- //' | sed 's/:.*//' || echo "") + + # If we have a previous decision and current state matches, skip asking + if [[ -n "$PROJECTS_DECISION" ]]; then + if [[ "$PROJECTS_DECISION" == "yes" ]] && [[ -n "$current_projects" ]]; then + log_info "Projects directory already configured: $current_projects" + return 0 + elif [[ "$PROJECTS_DECISION" == "no" ]] && [[ -z "$current_projects" ]]; then + log_info "Projects directory already disabled (user preference)" + return 0 fi fi - if [[ $has_projects -eq 0 ]]; then - read -p "Do you want to mount a Projects directory? (Y/n): " -n 1 -r - echo - if [[ ! $REPLY =~ ^[Nn]$ ]]; then - read -p "Enter path to your projects directory [$default_projects]: " projects_dir - projects_dir=${projects_dir:-$default_projects} - - if [[ -d "$projects_dir" ]]; then - # Add projects directory to docker-compose.yml after Documents line + if [[ -n "$current_projects" ]]; then + echo " Current: $current_projects" + echo " Status: โœ… Enabled" + else + echo " Default: $default_projects" + echo " Status: โŒ Not configured" + fi + echo "" + + local reply + read -p "Mount Projects directory? [Y/n]: " reply + + case "$reply" in + [nN][oO]|[nN]) + # Remove Projects mounting + if [[ -n "$current_projects" ]]; then if [[ "$OSTYPE" == "darwin"* ]]; then - sed -i '' "/\$HOME\/Documents:/a\\ - - $projects_dir:/home/developer/Projects" docker-compose.yml + sed -i '' "\|$current_projects.*Projects|d" docker-compose.yml else - sed -i "/\$HOME\/Documents:/a\\ - - $projects_dir:/home/developer/Projects" docker-compose.yml + sed -i "\|$current_projects.*Projects|d" docker-compose.yml fi - log_success "Projects directory added: $projects_dir -> /home/developer/Projects" + log_success "Projects directory mounting removed" + fi + PROJECTS_DECISION="no" + ;; + *) + local projects_path + if [[ -n "$current_projects" ]]; then + read -p "Projects directory path [$current_projects]: " projects_path + projects_path=${projects_path:-$current_projects} else - log_warning "Directory $projects_dir does not exist, you can create it and rebuild later" + read -p "Projects directory path [$default_projects]: " projects_path + projects_path=${projects_path:-$default_projects} fi - fi - fi - - # Configure additional directories + + if [[ -d "$projects_path" ]]; then + # Remove existing Projects mount first + if [[ -n "$current_projects" ]]; then + if [[ "$OSTYPE" == "darwin"* ]]; then + sed -i '' "\|$current_projects.*Projects|d" docker-compose.yml + else + sed -i "\|$current_projects.*Projects|d" docker-compose.yml + fi + fi + + # Add new Projects mount + add_directory_mount "$projects_path" "/home/developer/Projects" + + PROJECTS_DECISION="yes" + PROJECTS_PATH="$projects_path" + log_success "Projects directory configured: $projects_path" + else + log_error "Directory does not exist: $projects_path" + PROJECTS_DECISION="no" + fi + ;; + esac +} + +# Interactive menu for additional directories +configure_additional_directories() { + echo "" + echo "๐Ÿ“‚ Additional Directory Management:" echo "" - echo "๐Ÿ“‚ Additional Directories:" - read -p "Do you want to add/modify additional directories? (y/N): " -n 1 -r - echo - if [[ $REPLY =~ ^[Yy]$ ]]; then + + while true; do + echo "Choose an option:" + echo " ${GREEN}1.${NC} Add custom directory mount" + echo " ${YELLOW}2.${NC} Remove directory mount" + echo " ${BLUE}3.${NC} List current mounts" + echo " ${RED}4.${NC} Continue with configuration" echo "" - echo "Options:" - echo " 1. Add a new directory" - echo " 2. Remove a directory mount" - echo " 3. Done" + + read -p "Select option (1-4): " choice echo "" - while true; do - read -p "Select option (1-3): " -n 1 -r - echo - case $REPLY in - 1) - read -p "Enter directory path to mount: " custom_dir - if [[ -d "$custom_dir" ]]; then - local mount_name=$(basename "$custom_dir") - read -p "Mount as [/home/developer/$mount_name]: " container_path - container_path=${container_path:-"/home/developer/$mount_name"} - - # Add custom directory to docker-compose.yml - if [[ "$OSTYPE" == "darwin"* ]]; then - sed -i '' "/\$HOME\/Documents:/a\\ - - $custom_dir:$container_path" docker-compose.yml - else - sed -i "/\$HOME\/Documents:/a\\ - - $custom_dir:$container_path" docker-compose.yml - fi - log_success "Added: $custom_dir -> $container_path" - else - log_warning "Directory $custom_dir does not exist" - fi - ;; - 2) - echo "Current custom mounts (excluding system directories):" - grep -E "^\s*-\s+.*:.*$" docker-compose.yml | grep -v -E "(cache|npm|pip|Documents|\.dotfiles)" | nl - read -p "Enter line number to remove (or 'cancel'): " line_num - if [[ "$line_num" =~ ^[0-9]+$ ]]; then - # This is complex, let's just show instructions - log_info "Please manually edit docker-compose.yml to remove unwanted mounts" - fi - ;; - 3) - break - ;; - *) - echo "Invalid option. Please select 1, 2, or 3." - ;; - esac - echo "" - done - fi - - log_success "Directory configuration completed" + case "$choice" in + 1) + read -p "Enter directory path to mount: " custom_dir + if [[ -z "$custom_dir" ]]; then + log_warning "No directory specified" + continue + fi + + # Expand ~ to $HOME + if [[ "$custom_dir" =~ ^~ ]]; then + custom_dir="${custom_dir/#\~/$HOME}" + fi + + if [[ ! -d "$custom_dir" ]]; then + log_error "Directory does not exist: $custom_dir" + continue + fi + + local mount_name=$(basename "$custom_dir") + read -p "Mount as [/home/developer/$mount_name]: " container_path + container_path=${container_path:-"/home/developer/$mount_name"} + + if add_directory_mount "$custom_dir" "$container_path"; then + echo "" + log_success "Mount added successfully!" + else + echo "" + log_error "Failed to add mount" + fi + ;; + 2) + echo "Select directory mount to remove:" + echo "" + local mount_count + mount_count=$(get_current_mounts "true") + + if [[ "$mount_count" -eq 0 ]]; then + echo "" + log_warning "No mounts available to remove" + continue + fi + + echo "" + read -p "Enter number to remove (or 'cancel'): " selection + + if [[ "$selection" == "cancel" ]] || [[ "$selection" == "c" ]]; then + log_info "Removal cancelled" + continue + fi + + if remove_directory_mount "$selection"; then + echo "" + log_success "Mount removed successfully!" + else + echo "" + log_error "Failed to remove mount" + fi + ;; + 3) + get_current_mounts "false" + ;; + 4) + break + ;; + *) + log_warning "Invalid option. Please select 1-4." + ;; + esac + echo "" + done } -# Main function +# Main configuration flow main() { print_header - # Check if we're in the right directory - if [[ ! -f "docker-compose.yml" ]]; then - log_error "This script must be run from the lazyvim-docker directory" - echo "If you installed remotely, use: lazy configure" - exit 1 - fi + # Load previous configuration + load_config - log_info "This will help you reconfigure your LazyVim Docker environment." + log_step "Starting LazyVim Docker configuration..." echo "" - # Show current configuration - local current_tz=$(grep "TIMEZONE:" docker-compose.yml | awk '{print $2}' || echo "Not set") - echo "Current Configuration:" - echo " Timezone: $current_tz" - echo " Container: $(docker ps -q -f name=lazyvim >/dev/null 2>&1 && echo "Running" || echo "Stopped")" + # Configure timezone + configure_timezone echo "" - # Ask what to configure - echo "What would you like to configure?" - echo " 1. Timezone only" - echo " 2. Directory mounts only" - echo " 3. Both timezone and directories" - echo " 4. Exit" + # Configure directories + log_step "Configuring directory mounts..." echo "" - read -p "Select option (1-4): " -n 1 -r - echo - case $REPLY in - 1) - configure_timezone - ;; - 2) - configure_directories - ;; - 3) - configure_timezone - echo "" - configure_directories - ;; - 4) - log_info "Configuration cancelled" - exit 0 - ;; - *) - log_error "Invalid option selected" - exit 1 - ;; - esac + # Configure Documents directory (with memory) + configure_documents_directory + + # Configure Projects directory (with memory) + configure_projects_directory + + # Configure additional directories (interactive menu) + configure_additional_directories + + # Save configuration + save_config echo "" log_success "Configuration completed!" echo "" echo "Next steps:" - echo " 1. Rebuild container: make build" - echo " 2. Or restart if already built: make restart" - echo " 3. Enter container: make enter" + echo " ${CYAN}1.${NC} Run: ${GREEN}make build${NC} or ${GREEN}lazy build${NC} to rebuild the container" + echo " ${CYAN}2.${NC} Run: ${GREEN}make start${NC} or ${GREEN}lazy start${NC} to start LazyVim" + echo "" + echo "Your mounted directories will be available inside the container at:" + get_current_mounts "false" echo "" - echo "Changes will take effect after rebuilding/restarting the container." } # Run main function From 24c41d3ad13061f134132f66a173255faeb95186 Mon Sep 17 00:00:00 2001 From: Ricardo <31641216+manghidev@users.noreply.github.com> Date: Wed, 2 Jul 2025 13:55:11 -0600 Subject: [PATCH 12/20] feat: add LazyVim Docker configuration and enhance scripts --- .gitignore | 3 + debug_mounts.sh | 103 +++++++++ scripts/build.sh | 8 +- scripts/bump-version.sh | 12 +- scripts/check-timezone.sh | 28 +-- scripts/configure.sh | 324 ++++++++++++++++++--------- scripts/destroy.sh | 8 +- scripts/health-check.sh | 40 ++-- scripts/init.sh | 8 +- scripts/install-global-commands.sh | 16 +- scripts/remote-uninstall.sh | 18 +- scripts/start.sh | 20 +- scripts/uninstall-global-commands.sh | 22 +- test_mounts.sh | 12 + 14 files changed, 427 insertions(+), 195 deletions(-) create mode 100644 debug_mounts.sh create mode 100644 test_mounts.sh diff --git a/.gitignore b/.gitignore index 66c267c..4c43963 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,9 @@ .dotfiles/.zcompdump-* .dotfiles/.zsh_history +# LazyVim Docker configuration +.lazyvim-docker-config + # Backup files backups/ *.backup diff --git a/debug_mounts.sh b/debug_mounts.sh new file mode 100644 index 0000000..8d09d38 --- /dev/null +++ b/debug_mounts.sh @@ -0,0 +1,103 @@ +#!/bin/bash + +# Colors +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +CYAN='\033[0;36m' +PURPLE='\033[0;35m' +GRAY='\033[0;37m' +NC='\033[0m' + +# Test get_current_mounts with numbers +get_current_mounts_test() { + local show_numbers="${1:-false}" + local counter=1 + local mounts_found=false + local mounts_data=() + + printf "${CYAN}๐Ÿ“ Current Directory Mounts (Test):${NC}\n" + printf "โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”\n" + + # Parse docker-compose.yml for volume mounts - look in volumes section + local in_volumes_section=false + while IFS= read -r line; do + # Debug output + echo "DEBUG: Processing line: $line" >&2 + + # Check if we're entering volumes section + if [[ "$line" =~ ^[[:space:]]*volumes:[[:space:]]*$ ]]; then + in_volumes_section=true + echo "DEBUG: Entered volumes section" >&2 + continue + fi + + # Check if we're leaving volumes section (next main section) + if [[ "$in_volumes_section" == "true" ]] && [[ "$line" =~ ^[[:space:]]*[a-zA-Z_-]+:[[:space:]]*$ ]] && [[ ! "$line" =~ volumes: ]]; then + in_volumes_section=false + echo "DEBUG: Left volumes section" >&2 + continue + fi + + # Process volume mounts only within volumes section + if [[ "$in_volumes_section" == "true" ]] && [[ "$line" =~ ^[[:space:]]*-[[:space:]]+([^:]+):([^:]+)$ ]]; then + local host_path="${BASH_REMATCH[1]}" + local container_path="${BASH_REMATCH[2]}" + + echo "DEBUG: Found mount: $host_path -> $container_path" >&2 + + # Skip ONLY system caches and configs, NOT user dotfiles + if [[ "$container_path" =~ (/root/\.cache|/home/developer/\.cache|/tmp|cache|\.npm|\.pip|\.yarn) ]]; then + echo "DEBUG: Skipping system mount: $container_path" >&2 + continue + fi + + # Expand environment variables for display + local display_host_path="$host_path" + if [[ "$host_path" =~ ^\$HOME ]]; then + display_host_path="${host_path/\$HOME/$HOME}" + fi + + # Store mount data for potential removal + mounts_data+=("$host_path:$container_path") + + # Show numbered list if requested + if [[ "$show_numbers" == "true" ]]; then + printf "${YELLOW}%2d.${NC} " "$counter" + else + printf " ${PURPLE}โ€ข${NC} " + fi + + printf "${GREEN}Host:${NC} %s\n" "$display_host_path" + printf " ${CYAN}โ†’${NC} Container: %s\n" "$container_path" + + # Check if directory exists + if [[ -d "$display_host_path" ]]; then + printf " ${BLUE}Status:${NC} ${GREEN}โœ… Exists${NC}\n" + else + printf " ${BLUE}Status:${NC} ${RED}โŒ Missing${NC}\n" + fi + printf "\n" + + counter=$((counter + 1)) + mounts_found=true + fi + done < docker-compose.yml + + if [[ "$mounts_found" != "true" ]]; then + printf " ${GRAY}No custom directory mounts configured${NC}\n" + printf "\n" + fi + + printf "โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”\n" + + # Export mounts data for removal function + export CURRENT_MOUNTS_DATA="${mounts_data[*]}" + echo "DEBUG: Total mounts found: $((counter - 1))" >&2 + echo "DEBUG: Mounts data: $CURRENT_MOUNTS_DATA" >&2 + return $((counter - 1)) # Return total count +} + +echo "Testing get_current_mounts with show_numbers=true" +get_current_mounts_test "true" diff --git a/scripts/build.sh b/scripts/build.sh index 83923f3..c244b46 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -22,19 +22,19 @@ DOTFILES_DIR=".dotfiles" # Functions log_info() { - echo -e "${BLUE}[INFO]${NC} $1" + printf "${BLUE}[INFO]${NC} %s\n" "$1" } log_success() { - echo -e "${GREEN}[SUCCESS]${NC} $1" + printf "${GREEN}[SUCCESS]${NC} %s\n" "$1" } log_warning() { - echo -e "${YELLOW}[WARNING]${NC} $1" + printf "${YELLOW}[WARNING]${NC} %s\n" "$1" } log_error() { - echo -e "${RED}[ERROR]${NC} $1" + printf "${RED}[ERROR]${NC} %s\n" "$1" } # Check if VERSION file exists diff --git a/scripts/bump-version.sh b/scripts/bump-version.sh index 5c9dda4..07717ec 100755 --- a/scripts/bump-version.sh +++ b/scripts/bump-version.sh @@ -17,18 +17,18 @@ NC='\033[0m' # Validate bump type if [[ ! "$BUMP_TYPE" =~ ^(patch|minor|major)$ ]]; then - echo -e "${RED}Error: Invalid bump type. Use: patch, minor, or major${NC}" + printf "${RED}Error: Invalid bump type. Use: patch, minor, or major${NC}\n" exit 1 fi # Read current version if [[ ! -f "$VERSION_FILE" ]]; then - echo -e "${RED}Error: VERSION file not found${NC}" + printf "${RED}Error: VERSION file not found${NC}\n" exit 1 fi CURRENT_VERSION=$(cat "$VERSION_FILE") -echo -e "${BLUE}Current version: $CURRENT_VERSION${NC}" +printf "${BLUE}Current version: $CURRENT_VERSION${NC}\n" # Parse version components IFS='.' read -ra VERSION_PARTS <<< "$CURRENT_VERSION" @@ -56,13 +56,13 @@ NEW_VERSION="$MAJOR.$MINOR.$PATCH" # Write new version echo "$NEW_VERSION" > "$VERSION_FILE" -echo -e "${GREEN}Version bumped to: $NEW_VERSION${NC}" +printf "${GREEN}Version bumped to: $NEW_VERSION${NC}\n" # Git commit if in a git repository if git rev-parse --git-dir > /dev/null 2>&1; then - echo -e "${YELLOW}Committing version bump...${NC}" + printf "${YELLOW}Committing version bump...${NC}\n" git add "$VERSION_FILE" git commit -m "Bump version to $NEW_VERSION" git tag "v$NEW_VERSION" - echo -e "${GREEN}Version committed and tagged${NC}" + printf "${GREEN}Version committed and tagged${NC}\n" fi diff --git a/scripts/check-timezone.sh b/scripts/check-timezone.sh index 1d5d217..b029572 100755 --- a/scripts/check-timezone.sh +++ b/scripts/check-timezone.sh @@ -12,24 +12,24 @@ NC='\033[0m' CONTAINER_NAME="lazyvim" -echo -e "${BLUE}Checking timezone configuration...${NC}" -echo "" +printf "${BLUE}Checking timezone configuration...${NC}\n" +printf "\n" if docker ps | grep -q "$CONTAINER_NAME"; then - echo -e "${GREEN}Container timezone information:${NC}" - echo "Current time in container:" + printf "${GREEN}Container timezone information:${NC}\n" + printf "Current time in container:\n" docker exec "$CONTAINER_NAME" date - echo "" - echo "Timezone file:" - docker exec "$CONTAINER_NAME" cat /etc/timezone 2>/dev/null || echo "Timezone file not found" - echo "" - echo "TZ environment variable:" - docker exec "$CONTAINER_NAME" env | grep TZ || echo "TZ variable not set" - echo "" - echo -e "${GREEN}Local system time for comparison:${NC}" + printf "\n" + printf "Timezone file:\n" + docker exec "$CONTAINER_NAME" cat /etc/timezone 2>/dev/null || printf "Timezone file not found\n" + printf "\n" + printf "TZ environment variable:\n" + docker exec "$CONTAINER_NAME" env | grep TZ || printf "TZ variable not set\n" + printf "\n" + printf "${GREEN}Local system time for comparison:${NC}\n" date else - echo "Container '$CONTAINER_NAME' is not running." - echo "Please start the container first with: make start" + printf "Container '%s' is not running.\n" "$CONTAINER_NAME" + printf "Please start the container first with: make start\n" exit 1 fi diff --git a/scripts/configure.sh b/scripts/configure.sh index 53785fe..8bab0d3 100755 --- a/scripts/configure.sh +++ b/scripts/configure.sh @@ -25,31 +25,31 @@ CONFIG_FILE=".lazyvim-docker-config" # Functions log_info() { - echo -e "${BLUE}โ„น๏ธ ${NC} $1" + printf "${BLUE}โ„น๏ธ ${NC} %s\n" "$1" } log_success() { - echo -e "${GREEN}โœ… ${NC} $1" + printf "${GREEN}โœ… ${NC} %s\n" "$1" } log_warning() { - echo -e "${YELLOW}โš ๏ธ ${NC} $1" + printf "${YELLOW}โš ๏ธ ${NC} %s\n" "$1" } log_error() { - echo -e "${RED}โŒ ${NC} $1" + printf "${RED}โŒ ${NC} %s\n" "$1" } log_step() { - echo -e "${PURPLE}๐Ÿ”ง ${NC} $1" + printf "${PURPLE}๐Ÿ”ง ${NC} %s\n" "$1" } print_header() { - echo -e "${CYAN}โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—${NC}" - echo -e "${CYAN}โ•‘ LazyVim Docker - Smart Configuration Tool โ•‘${NC}" - echo -e "${CYAN}โ•‘ Improved Directory & Timezone Manager v2.0 โ•‘${NC}" - echo -e "${CYAN}โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•${NC}" - echo "" + printf "${CYAN}โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—${NC}\n" + printf "${CYAN}โ•‘ LazyVim Docker - Smart Configuration Tool โ•‘${NC}\n" + printf "${CYAN}โ•‘ Improved Directory & Timezone Manager v2.0 โ•‘${NC}\n" + printf "${CYAN}โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•${NC}\n" + printf "\n" } # Load user preferences @@ -85,13 +85,29 @@ is_mount_exists() { normalized_path="${host_path/\$HOME/$HOME}" fi - # Check if mount exists (non-commented line) - if grep -v "^[[:space:]]*#" docker-compose.yml | grep -q "- $host_path:" || \ - grep -v "^[[:space:]]*#" docker-compose.yml | grep -q "- $normalized_path:"; then - return 0 # Mount exists - else - return 1 # Mount doesn't exist - fi + # Check if mount exists in volumes section (non-commented line) + local in_volumes_section=false + while IFS= read -r line; do + # Check if we're entering volumes section + if [[ "$line" =~ ^[[:space:]]*volumes:[[:space:]]*$ ]]; then + in_volumes_section=true + continue + fi + + # Check if we're leaving volumes section (next main section) + if [[ "$in_volumes_section" == "true" ]] && [[ "$line" =~ ^[[:space:]]*[a-zA-Z_-]+:[[:space:]]*$ ]] && [[ ! "$line" =~ volumes: ]]; then + in_volumes_section=false + continue + fi + + # Check for mount within volumes section (non-commented) + if [[ "$in_volumes_section" == "true" ]] && [[ ! "$line" =~ ^[[:space:]]*# ]] && \ + ([[ "$line" =~ "$host_path:" ]] || [[ "$line" =~ "$normalized_path:" ]]); then + return 0 # Mount exists + fi + done < docker-compose.yml + + return 1 # Mount doesn't exist } # Get all current mounts in a structured way @@ -101,17 +117,31 @@ get_current_mounts() { local mounts_found=false local mounts_data=() - echo -e "${CYAN}๐Ÿ“ Current Directory Mounts:${NC}" - echo "โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”" + printf "${CYAN}๐Ÿ“ Current Directory Mounts:${NC}\n" + printf "โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”\n" - # Parse docker-compose.yml for volume mounts + # Parse docker-compose.yml for volume mounts - look in volumes section + local in_volumes_section=false while IFS= read -r line; do - if [[ "$line" =~ ^[[:space:]]*-[[:space:]]+([^:]+):([^:]+)$ ]]; then + # Check if we're entering volumes section + if [[ "$line" =~ ^[[:space:]]*volumes:[[:space:]]*$ ]]; then + in_volumes_section=true + continue + fi + + # Check if we're leaving volumes section (next main section) + if [[ "$in_volumes_section" == "true" ]] && [[ "$line" =~ ^[[:space:]]*[a-zA-Z_-]+:[[:space:]]*$ ]] && [[ ! "$line" =~ volumes: ]]; then + in_volumes_section=false + continue + fi + + # Process volume mounts only within volumes section + if [[ "$in_volumes_section" == "true" ]] && [[ "$line" =~ ^[[:space:]]*-[[:space:]]+([^:]+):([^:]+)$ ]]; then local host_path="${BASH_REMATCH[1]}" local container_path="${BASH_REMATCH[2]}" - # Skip system mounts (cache, npm, etc.) - if [[ "$container_path" =~ (cache|npm|pip|yarn|\.dotfiles|\.ssh|config/nvim) ]]; then + # Skip ONLY system caches and configs, NOT user dotfiles + if [[ "$container_path" =~ (/root/\.cache|/home/developer/\.cache|/tmp|cache|\.npm|\.pip|\.yarn) ]]; then continue fi @@ -140,23 +170,26 @@ get_current_mounts() { else printf " ${BLUE}Status:${NC} ${RED}โŒ Missing${NC}\n" fi - echo "" + printf "\n" counter=$((counter + 1)) mounts_found=true fi - done < <(grep -v "^[[:space:]]*#" docker-compose.yml | grep -E "^\s*-\s+.*:.*$") + done < docker-compose.yml if [[ "$mounts_found" != "true" ]]; then - echo " ${GRAY}No custom directory mounts configured${NC}" - echo "" + printf " ${GRAY}No custom directory mounts configured${NC}\n" + printf "\n" fi - echo "โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”" + printf "โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”\n" # Export mounts data for removal function export CURRENT_MOUNTS_DATA="${mounts_data[*]}" - return $((counter - 1)) # Return total count + + # Return 0 always to avoid script termination + echo "$((counter - 1))" > /tmp/mount_count + return 0 } # Add a directory mount (prevents duplicates) @@ -176,23 +209,25 @@ add_directory_mount() { return 1 fi - # Add mount after the Documents line or at the end of volumes section + # Add mount after the Documents line or at the appropriate place in volumes section if grep -q "Documents:" docker-compose.yml; then - # Add after Documents line + # Add after Documents line with proper formatting if [[ "$OSTYPE" == "darwin"* ]]; then sed -i '' "/\$HOME\/Documents:/a\\ - - $host_path:$container_path" docker-compose.yml + - $host_path:$container_path\\ +" docker-compose.yml else sed -i "/\$HOME\/Documents:/a\\ - $host_path:$container_path" docker-compose.yml fi else - # Find volumes section and add there + # Find the end of mount directories section and add there if [[ "$OSTYPE" == "darwin"* ]]; then - sed -i '' "/volumes:/a\\ - - $host_path:$container_path" docker-compose.yml + sed -i '' "/# - \$HOME\/Documents:/a\\ + - $host_path:$container_path\\ +" docker-compose.yml else - sed -i "/volumes:/a\\ + sed -i "/# - \$HOME\/Documents:/a\\ - $host_path:$container_path" docker-compose.yml fi fi @@ -205,25 +240,54 @@ add_directory_mount() { remove_directory_mount() { local selection="$1" - # Get current mounts data - get_current_mounts "false" > /dev/null + # Get current mounts data directly + local mounts_data=() + local counter=1 - if [[ -z "$CURRENT_MOUNTS_DATA" ]]; then + # Parse docker-compose.yml for volume mounts - look in volumes section + local in_volumes_section=false + while IFS= read -r line; do + # Check if we're entering volumes section + if [[ "$line" =~ ^[[:space:]]*volumes:[[:space:]]*$ ]]; then + in_volumes_section=true + continue + fi + + # Check if we're leaving volumes section (next main section) + if [[ "$in_volumes_section" == "true" ]] && [[ "$line" =~ ^[[:space:]]*[a-zA-Z_-]+:[[:space:]]*$ ]] && [[ ! "$line" =~ volumes: ]]; then + in_volumes_section=false + continue + fi + + # Process volume mounts only within volumes section + if [[ "$in_volumes_section" == "true" ]] && [[ "$line" =~ ^[[:space:]]*-[[:space:]]+([^:]+):([^:]+)$ ]]; then + local host_path="${BASH_REMATCH[1]}" + local container_path="${BASH_REMATCH[2]}" + + # Skip ONLY system caches and configs, NOT user dotfiles + if [[ "$container_path" =~ (/root/\.cache|/home/developer/\.cache|/tmp|cache|\.npm|\.pip|\.yarn) ]]; then + continue + fi + + # Store mount data for potential removal + mounts_data+=("$host_path:$container_path") + counter=$((counter + 1)) + fi + done < docker-compose.yml + + if [[ ${#mounts_data[@]} -eq 0 ]]; then log_warning "No mounts available to remove" return 1 fi - # Convert space-separated data to array - IFS=' ' read -ra mounts_array <<< "$CURRENT_MOUNTS_DATA" - # Validate selection - if [[ ! "$selection" =~ ^[0-9]+$ ]] || [[ "$selection" -lt 1 ]] || [[ "$selection" -gt "${#mounts_array[@]}" ]]; then + if [[ ! "$selection" =~ ^[0-9]+$ ]] || [[ "$selection" -lt 1 ]] || [[ "$selection" -gt "${#mounts_data[@]}" ]]; then log_error "Invalid selection: $selection" return 1 fi # Get the mount to remove (1-indexed to 0-indexed) - local mount_to_remove="${mounts_array[$((selection - 1))]}" + local mount_to_remove="${mounts_data[$((selection - 1))]}" local host_path="${mount_to_remove%:*}" local container_path="${mount_to_remove#*:}" @@ -256,10 +320,10 @@ configure_timezone() { local current_tz=$(grep "TIMEZONE:" docker-compose.yml | awk '{print $2}' 2>/dev/null || echo "") local default_tz="${system_tz:-America/Mexico_City}" - echo "๐ŸŒ Timezone Configuration:" - echo " Current in container: ${current_tz:-"Not set"}" - echo " System timezone: ${system_tz:-"Could not detect"}" - echo "" + printf "๐ŸŒ Timezone Configuration:\n" + printf " Current in container: %s\n" "${current_tz:-"Not set"}" + printf " System timezone: %s\n" "${system_tz:-"Could not detect"}" + printf "\n" # If we have a previous timezone decision and it matches current, skip if [[ -n "$LAST_TIMEZONE" ]] && [[ "$LAST_TIMEZONE" == "$current_tz" ]]; then @@ -267,14 +331,14 @@ configure_timezone() { return 0 fi - echo "Available timezone examples:" - echo " - America/New_York" - echo " - America/Los_Angeles" - echo " - America/Mexico_City" - echo " - Europe/London" - echo " - Europe/Madrid" - echo " - Asia/Tokyo" - echo "" + printf "Available timezone examples:\n" + printf " - America/New_York\n" + printf " - America/Los_Angeles\n" + printf " - America/Mexico_City\n" + printf " - Europe/London\n" + printf " - Europe/Madrid\n" + printf " - Asia/Tokyo\n" + printf "\n" read -p "Enter timezone [$default_tz]: " timezone timezone=${timezone:-$default_tz} @@ -294,7 +358,7 @@ configure_timezone() { configure_documents_directory() { local default_docs="$HOME/Documents" - echo "๐Ÿ“„ Documents Directory Configuration:" + printf "๐Ÿ“„ Documents Directory Configuration:\n" # Check if Documents directory exists if [[ ! -d "$default_docs" ]]; then @@ -303,7 +367,7 @@ configure_documents_directory() { fi # Check current state in docker-compose.yml - local is_enabled=$(grep -v "^[[:space:]]*#" docker-compose.yml | grep -q "\$HOME/Documents:" && echo "yes" || echo "no") + local is_enabled=$(grep -v "^[[:space:]]*#" docker-compose.yml | grep -q "\$HOME/Documents:" && printf "yes" || printf "no") # If we have a previous decision and current state matches, skip asking if [[ -n "$DOCUMENTS_DECISION" ]]; then @@ -316,9 +380,9 @@ configure_documents_directory() { fi fi - echo " Path: $default_docs" - echo " Status: $([ "$is_enabled" == "yes" ] && echo "โœ… Enabled" || echo "โŒ Disabled")" - echo "" + printf " Path: %s\n" "$default_docs" + printf " Status: %s\n" "$([ "$is_enabled" == "yes" ] && printf "โœ… Enabled" || printf "โŒ Disabled")" + printf "\n" local reply read -p "Mount Documents directory? [Y/n]: " reply @@ -357,11 +421,11 @@ configure_projects_directory() { default_projects="$HOME/Projects" fi - echo "" - echo "๐Ÿ’ป Projects Directory Configuration:" + printf "\n" + printf "๐Ÿ’ป Projects Directory Configuration:\n" # Get current Projects mount if exists - local current_projects=$(grep -v "^[[:space:]]*#" docker-compose.yml | grep "Projects:/home/developer/Projects" | sed 's/.*- //' | sed 's/:.*//' || echo "") + local current_projects=$(grep -v "^[[:space:]]*#" docker-compose.yml | grep "Projects:/home/developer/Projects" | sed 's/.*- //' | sed 's/:.*//' || printf "") # If we have a previous decision and current state matches, skip asking if [[ -n "$PROJECTS_DECISION" ]]; then @@ -375,13 +439,13 @@ configure_projects_directory() { fi if [[ -n "$current_projects" ]]; then - echo " Current: $current_projects" - echo " Status: โœ… Enabled" + printf " Current: %s\n" "$current_projects" + printf " Status: โœ… Enabled\n" else - echo " Default: $default_projects" - echo " Status: โŒ Not configured" + printf " Default: %s\n" "$default_projects" + printf " Status: โŒ Not configured\n" fi - echo "" + printf "\n" local reply read -p "Mount Projects directory? [Y/n]: " reply @@ -435,20 +499,21 @@ configure_projects_directory() { # Interactive menu for additional directories configure_additional_directories() { - echo "" - echo "๐Ÿ“‚ Additional Directory Management:" - echo "" + printf "\n" + printf "๐Ÿ“‚ Additional Directory Management:\n" + printf "\n" while true; do - echo "Choose an option:" - echo " ${GREEN}1.${NC} Add custom directory mount" - echo " ${YELLOW}2.${NC} Remove directory mount" - echo " ${BLUE}3.${NC} List current mounts" - echo " ${RED}4.${NC} Continue with configuration" - echo "" + printf "Choose an option:\n" + printf " ${GREEN}1.${NC} Add custom directory mount\n" + printf " ${YELLOW}2.${NC} Remove directory mount\n" + printf " ${BLUE}3.${NC} List current mounts\n" + printf " ${PURPLE}4.${NC} Add multiple directories at once\n" + printf " ${RED}5.${NC} Continue with configuration\n" + printf "\n" - read -p "Select option (1-4): " choice - echo "" + read -p "Select option (1-5): " choice + printf "\n" case "$choice" in 1) @@ -473,26 +538,28 @@ configure_additional_directories() { container_path=${container_path:-"/home/developer/$mount_name"} if add_directory_mount "$custom_dir" "$container_path"; then - echo "" + printf "\n" log_success "Mount added successfully!" else - echo "" + printf "\n" log_error "Failed to add mount" fi ;; 2) - echo "Select directory mount to remove:" - echo "" - local mount_count - mount_count=$(get_current_mounts "true") + printf "Select directory mount to remove:\n" + printf "\n" + + # Get and show numbered list + get_current_mounts "true" + local mount_count=$(cat /tmp/mount_count 2>/dev/null || echo "0") if [[ "$mount_count" -eq 0 ]]; then - echo "" + printf "\n" log_warning "No mounts available to remove" continue fi - echo "" + printf "\n" read -p "Enter number to remove (or 'cancel'): " selection if [[ "$selection" == "cancel" ]] || [[ "$selection" == "c" ]]; then @@ -501,10 +568,10 @@ configure_additional_directories() { fi if remove_directory_mount "$selection"; then - echo "" + printf "\n" log_success "Mount removed successfully!" else - echo "" + printf "\n" log_error "Failed to remove mount" fi ;; @@ -512,13 +579,52 @@ configure_additional_directories() { get_current_mounts "false" ;; 4) + printf "Enter multiple directories (one per line, empty line to finish):\n" + local dirs_to_add=() + while true; do + read -p "Directory path: " dir_path + if [[ -z "$dir_path" ]]; then + break + fi + + # Expand ~ to $HOME + if [[ "$dir_path" =~ ^~ ]]; then + dir_path="${dir_path/#\~/$HOME}" + fi + + if [[ -d "$dir_path" ]]; then + dirs_to_add+=("$dir_path") + printf " ${GREEN}โœ“${NC} Added to queue: $dir_path\n" + else + printf " ${RED}โœ—${NC} Directory not found: $dir_path\n" + fi + done + + if [[ ${#dirs_to_add[@]} -gt 0 ]]; then + printf "\nAdding ${#dirs_to_add[@]} directories...\n" + for dir in "${dirs_to_add[@]}"; do + local mount_name=$(basename "$dir") + local container_path="/home/developer/$mount_name" + if add_directory_mount "$dir" "$container_path"; then + log_success "Added: $dir โ†’ $container_path" + else + log_error "Failed to add: $dir" + fi + done + printf "\n" + log_success "Batch addition completed!" + else + log_info "No directories were added" + fi + ;; + 5) break ;; *) - log_warning "Invalid option. Please select 1-4." + log_warning "Invalid option. Please select 1-5." ;; esac - echo "" + printf "\n" done } @@ -530,15 +636,15 @@ main() { load_config log_step "Starting LazyVim Docker configuration..." - echo "" + printf "\n" # Configure timezone configure_timezone - echo "" + printf "\n" # Configure directories log_step "Configuring directory mounts..." - echo "" + printf "\n" # Configure Documents directory (with memory) configure_documents_directory @@ -552,17 +658,25 @@ main() { # Save configuration save_config - echo "" + printf "\n" log_success "Configuration completed!" - echo "" - echo "Next steps:" - echo " ${CYAN}1.${NC} Run: ${GREEN}make build${NC} or ${GREEN}lazy build${NC} to rebuild the container" - echo " ${CYAN}2.${NC} Run: ${GREEN}make start${NC} or ${GREEN}lazy start${NC} to start LazyVim" - echo "" - echo "Your mounted directories will be available inside the container at:" + printf "\n" + printf "Next steps:\n" + printf " ${CYAN}1.${NC} Run: ${GREEN}make build${NC} or ${GREEN}lazy build${NC} to rebuild the container\n" + printf " ${CYAN}2.${NC} Run: ${GREEN}make start${NC} or ${GREEN}lazy start${NC} to start LazyVim\n" + printf "\n" + printf "Your mounted directories will be available inside the container at:\n" get_current_mounts "false" - echo "" + printf "\n" + + # Clean up temp files + rm -f /tmp/mount_count + + # Exit successfully + exit 0 } -# Run main function -main "$@" +# Run main function only if script is executed directly (not sourced) +if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then + main "$@" +fi diff --git a/scripts/destroy.sh b/scripts/destroy.sh index 298a1d4..9ed44e5 100755 --- a/scripts/destroy.sh +++ b/scripts/destroy.sh @@ -20,19 +20,19 @@ CONTAINER_NAME="lazyvim" # Functions log_info() { - echo -e "${BLUE}[INFO]${NC} $1" + printf "${BLUE}[INFO]${NC} %s\n" "$1" } log_success() { - echo -e "${GREEN}[SUCCESS]${NC} $1" + printf "${GREEN}[SUCCESS]${NC} %s\n" "$1" } log_warning() { - echo -e "${YELLOW}[WARNING]${NC} $1" + printf "${YELLOW}[WARNING]${NC} %s\n" "$1" } log_error() { - echo -e "${RED}[ERROR]${NC} $1" + printf "${RED}[ERROR]${NC} %s\n" "$1" } # Confirmation prompt diff --git a/scripts/health-check.sh b/scripts/health-check.sh index 507aaa9..07ab90b 100755 --- a/scripts/health-check.sh +++ b/scripts/health-check.sh @@ -17,30 +17,30 @@ CONTAINER_NAME="lazyvim" # Functions log_info() { - echo -e "${BLUE}[INFO]${NC} $1" + printf "${BLUE}[INFO]${NC} %s\n" "$1" } log_success() { - echo -e "${GREEN}[SUCCESS]${NC} $1" + printf "${GREEN}[SUCCESS]${NC} %s\n" "$1" } log_warning() { - echo -e "${YELLOW}[WARNING]${NC} $1" + printf "${YELLOW}[WARNING]${NC} %s\n" "$1" } log_error() { - echo -e "${RED}[ERROR]${NC} $1" + printf "${RED}[ERROR]${NC} %s\n" "$1" } print_header() { - echo -e "${BLUE}=== LazyVim Docker Health Check ===${NC}" - echo "" + printf "${BLUE}=== LazyVim Docker Health Check ===${NC}\n" + printf "\n" } print_separator() { - echo "" - echo "-----------------------------------" - echo "" + printf "\n" + printf -- "-----------------------------------\n" + printf "\n" } # Main health check function @@ -52,7 +52,7 @@ health_check() { if docker info >/dev/null 2>&1; then log_success "Docker is running" DOCKER_VERSION=$(docker --version) - echo " Version: $DOCKER_VERSION" + printf " Version: %s\n" "$DOCKER_VERSION" else log_error "Docker is not running or not installed" return 1 @@ -65,7 +65,7 @@ health_check() { if docker compose version >/dev/null 2>&1; then log_success "Docker Compose is available" COMPOSE_VERSION=$(docker compose version --short) - echo " Version: $COMPOSE_VERSION" + printf " Version: %s\n" "$COMPOSE_VERSION" else log_error "Docker Compose is not available" return 1 @@ -79,7 +79,7 @@ health_check() { if [ "$CONTAINER_STATE" = "missing" ]; then log_warning "Container does not exist" - echo " Use 'make build' to create it" + printf " Use 'make build' to create it\n" elif [ "$CONTAINER_STATE" = "running" ]; then log_success "Container is running" @@ -87,8 +87,8 @@ health_check() { log_info "Checking container health..." CONTAINER_HEALTH=$(docker inspect "$CONTAINER_NAME" --format='{{.State.Health.Status}}' 2>/dev/null || echo "No health check") - echo " Status: $CONTAINER_STATE" - echo " Health: $CONTAINER_HEALTH" + printf " Status: %s\n" "$CONTAINER_STATE" + printf " Health: %s\n" "$CONTAINER_HEALTH" # Check if we can execute commands in the container if docker exec "$CONTAINER_NAME" echo "Container accessible" >/dev/null 2>&1; then @@ -98,7 +98,7 @@ health_check() { fi else log_warning "Container exists but is stopped ($CONTAINER_STATE)" - echo " Use 'make start' to start it" + printf " Use 'make start' to start it\n" fi print_separator @@ -124,14 +124,14 @@ health_check() { DOTFILES=(".dotfiles/.zshrc" ".dotfiles/.p10k.zsh" ".dotfiles/.config/nvim" ".dotfiles/.config/lazygit") for file in "${DOTFILES[@]}"; do if [[ -e "$file" ]]; then - echo " โœ“ $file" + printf " โœ“ %s\n" "$file" else log_warning "Missing: $file" fi done else log_warning "Dotfiles directory does not exist" - echo " It will be created automatically when you build the environment" + printf " It will be created automatically when you build the environment\n" fi print_separator @@ -154,13 +154,13 @@ health_check() { if [ "$FINAL_CONTAINER_STATE" = "running" ]; then log_success "Environment is ready to use!" - echo " Use 'make enter' to access the container" + printf " Use 'make enter' to access the container\n" elif [ "$FINAL_CONTAINER_STATE" = "missing" ]; then log_info "Environment is not built" - echo " Use 'make build' to create the container" + printf " Use 'make build' to create the container\n" else log_info "Environment is not running" - echo " Use 'make start' to start the existing container" + printf " Use 'make start' to start the existing container\n" fi } diff --git a/scripts/init.sh b/scripts/init.sh index 373d506..ac11264 100755 --- a/scripts/init.sh +++ b/scripts/init.sh @@ -20,19 +20,19 @@ CONTAINER_NAME="lazyvim" # Functions log_info() { - echo -e "${BLUE}[INFO]${NC} $1" + printf "${BLUE}[INFO]${NC} %s\n" "$1" } log_success() { - echo -e "${GREEN}[SUCCESS]${NC} $1" + printf "${GREEN}[SUCCESS]${NC} %s\n" "$1" } log_warning() { - echo -e "${YELLOW}[WARNING]${NC} $1" + printf "${YELLOW}[WARNING]${NC} %s\n" "$1" } log_error() { - echo -e "${RED}[ERROR]${NC} $1" + printf "${RED}[ERROR]${NC} %s\n" "$1" } # Check if Docker is running diff --git a/scripts/install-global-commands.sh b/scripts/install-global-commands.sh index 75995fb..0be3965 100644 --- a/scripts/install-global-commands.sh +++ b/scripts/install-global-commands.sh @@ -14,19 +14,19 @@ NC='\033[0m' # Functions log_info() { - echo -e "${BLUE}[INFO]${NC} $1" + printf "${BLUE}[INFO]${NC} %s\n" "$1" } log_success() { - echo -e "${GREEN}[SUCCESS]${NC} $1" + printf "${GREEN}[SUCCESS]${NC} %s\n" "$1" } log_warning() { - echo -e "${YELLOW}[WARNING]${NC} $1" + printf "${YELLOW}[WARNING]${NC} %s\n" "$1" } log_error() { - echo -e "${RED}[ERROR]${NC} $1" + printf "${RED}[ERROR]${NC} %s\n" "$1" } # Get the absolute path of the lazyvim-docker directory @@ -264,16 +264,16 @@ install_global_commands() { local current_shell="" if [[ -n "$ZSH_VERSION" ]]; then current_shell="zsh" - echo -e "${GREEN}For your current Zsh session, run: source ~/.zshrc${NC}" + printf "${GREEN}For your current Zsh session, run: source ~/.zshrc${NC}\n" elif [[ -n "$BASH_VERSION" ]]; then current_shell="bash" - echo -e "${GREEN}For your current Bash session, run: source ~/.bashrc${NC}" + printf "${GREEN}For your current Bash session, run: source ~/.bashrc${NC}\n" elif [[ "$SHELL" == *"zsh"* ]]; then current_shell="zsh" - echo -e "${GREEN}For your current Zsh session, run: source ~/.zshrc${NC}" + printf "${GREEN}For your current Zsh session, run: source ~/.zshrc${NC}\n" else current_shell="bash" - echo -e "${GREEN}For your current Bash session, run: source ~/.bashrc${NC}" + printf "${GREEN}For your current Bash session, run: source ~/.bashrc${NC}\n" fi echo "" diff --git a/scripts/remote-uninstall.sh b/scripts/remote-uninstall.sh index 12307c9..c125ba4 100755 --- a/scripts/remote-uninstall.sh +++ b/scripts/remote-uninstall.sh @@ -20,30 +20,30 @@ BIN_DIR="$HOME/.local/bin" # Print functions print_header() { - echo -e "${CYAN}โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—${NC}" - echo -e "${CYAN}โ•‘ LazyVim Docker - Uninstaller โ•‘${NC}" - echo -e "${CYAN}โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•${NC}" - echo "" + printf "${CYAN}โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—${NC}\n" + printf "${CYAN}โ•‘ LazyVim Docker - Uninstaller โ•‘${NC}\n" + printf "${CYAN}โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•${NC}\n" + printf "\n" } print_info() { - echo -e "${BLUE}[INFO]${NC} $1" + printf "${BLUE}[INFO]${NC} %s\n" "$1" } print_success() { - echo -e "${GREEN}[SUCCESS]${NC} $1" + printf "${GREEN}[SUCCESS]${NC} %s\n" "$1" } print_warning() { - echo -e "${YELLOW}[WARNING]${NC} $1" + printf "${YELLOW}[WARNING]${NC} %s\n" "$1" } print_error() { - echo -e "${RED}[ERROR]${NC} $1" + printf "${RED}[ERROR]${NC} %s\n" "$1" } print_step() { - echo -e "${PURPLE}[STEP]${NC} $1" + printf "${PURPLE}[STEP]${NC} %s\n" "$1" } # Smart terminal restart for clean environment diff --git a/scripts/start.sh b/scripts/start.sh index 11a50db..300a385 100755 --- a/scripts/start.sh +++ b/scripts/start.sh @@ -25,31 +25,31 @@ BRANCH="${LAZYVIM_BRANCH:-develop}" # Print functions print_header() { - echo -e "${CYAN}โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—${NC}" - echo -e "${CYAN}โ•‘ LazyVim Docker - Quick Start โ•‘${NC}" - echo -e "${CYAN}โ•‘ One Command, Instant Development โ•‘${NC}" - echo -e "${CYAN}โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•${NC}" - echo "" + printf "${CYAN}โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—${NC}\n" + printf "${CYAN}โ•‘ LazyVim Docker - Quick Start โ•‘${NC}\n" + printf "${CYAN}โ•‘ One Command, Instant Development โ•‘${NC}\n" + printf "${CYAN}โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•${NC}\n" + printf "\n" } print_info() { - echo -e "${BLUE}[INFO]${NC} $1" + printf "${BLUE}[INFO]${NC} %s\n" "$1" } print_success() { - echo -e "${GREEN}[SUCCESS]${NC} $1" + printf "${GREEN}[SUCCESS]${NC} %s\n" "$1" } print_warning() { - echo -e "${YELLOW}[WARNING]${NC} $1" + printf "${YELLOW}[WARNING]${NC} %s\n" "$1" } print_error() { - echo -e "${RED}[ERROR]${NC} $1" + printf "${RED}[ERROR]${NC} %s\n" "$1" } print_step() { - echo -e "${PURPLE}[STEP]${NC} $1" + printf "${PURPLE}[STEP]${NC} %s\n" "$1" } # Smart terminal restart with helper script diff --git a/scripts/uninstall-global-commands.sh b/scripts/uninstall-global-commands.sh index ebecbbe..2219f5e 100755 --- a/scripts/uninstall-global-commands.sh +++ b/scripts/uninstall-global-commands.sh @@ -19,19 +19,19 @@ END_MARKER="# LazyVim Docker Global Commands - END" # Print colored output print_status() { - echo -e "${BLUE}[INFO]${NC} $1" + printf "${BLUE}[INFO]${NC} %s\n" "$1" } print_success() { - echo -e "${GREEN}[SUCCESS]${NC} $1" + printf "${GREEN}[SUCCESS]${NC} %s\n" "$1" } print_warning() { - echo -e "${YELLOW}[WARNING]${NC} $1" + printf "${YELLOW}[WARNING]${NC} %s\n" "$1" } print_error() { - echo -e "${RED}[ERROR]${NC} $1" + printf "${RED}[ERROR]${NC} %s\n" "$1" } # Function to remove commands from a specific shell config file @@ -145,18 +145,18 @@ remove_project_directory() { # Main function main() { - echo - echo -e "${BLUE}โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—${NC}" - echo -e "${BLUE}โ•‘ LazyVim Docker - Uninstaller โ•‘${NC}" - echo -e "${BLUE}โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•${NC}" - echo + printf "\n" + printf "${BLUE}โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—${NC}\n" + printf "${BLUE}โ•‘ LazyVim Docker - Uninstaller โ•‘${NC}\n" + printf "${BLUE}โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•${NC}\n" + printf "\n" # Remove global commands if remove_global_commands; then - echo + printf "\n" print_success "โœ“ Global 'lazy' commands removed from shell configurations" else - echo + printf "\n" print_warning "โš  No global commands were found to remove" fi diff --git a/test_mounts.sh b/test_mounts.sh new file mode 100644 index 0000000..0769b98 --- /dev/null +++ b/test_mounts.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +# Test file for get_current_mounts function +source scripts/configure.sh + +# Skip main execution by overriding it +main() { + echo "Testing get_current_mounts function..." + get_current_mounts "true" +} + +main From 5d9fa7ab52f360e6fc316ea2e723932ca930da44 Mon Sep 17 00:00:00 2001 From: Ricardo <31641216+manghidev@users.noreply.github.com> Date: Wed, 2 Jul 2025 13:56:17 -0600 Subject: [PATCH 13/20] refactor: remove debug_mounts.sh and test_mounts.sh scripts to streamline codebase --- debug_mounts.sh | 103 ------------------------------------------------ test_mounts.sh | 12 ------ 2 files changed, 115 deletions(-) delete mode 100644 debug_mounts.sh delete mode 100644 test_mounts.sh diff --git a/debug_mounts.sh b/debug_mounts.sh deleted file mode 100644 index 8d09d38..0000000 --- a/debug_mounts.sh +++ /dev/null @@ -1,103 +0,0 @@ -#!/bin/bash - -# Colors -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -BLUE='\033[0;34m' -CYAN='\033[0;36m' -PURPLE='\033[0;35m' -GRAY='\033[0;37m' -NC='\033[0m' - -# Test get_current_mounts with numbers -get_current_mounts_test() { - local show_numbers="${1:-false}" - local counter=1 - local mounts_found=false - local mounts_data=() - - printf "${CYAN}๐Ÿ“ Current Directory Mounts (Test):${NC}\n" - printf "โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”\n" - - # Parse docker-compose.yml for volume mounts - look in volumes section - local in_volumes_section=false - while IFS= read -r line; do - # Debug output - echo "DEBUG: Processing line: $line" >&2 - - # Check if we're entering volumes section - if [[ "$line" =~ ^[[:space:]]*volumes:[[:space:]]*$ ]]; then - in_volumes_section=true - echo "DEBUG: Entered volumes section" >&2 - continue - fi - - # Check if we're leaving volumes section (next main section) - if [[ "$in_volumes_section" == "true" ]] && [[ "$line" =~ ^[[:space:]]*[a-zA-Z_-]+:[[:space:]]*$ ]] && [[ ! "$line" =~ volumes: ]]; then - in_volumes_section=false - echo "DEBUG: Left volumes section" >&2 - continue - fi - - # Process volume mounts only within volumes section - if [[ "$in_volumes_section" == "true" ]] && [[ "$line" =~ ^[[:space:]]*-[[:space:]]+([^:]+):([^:]+)$ ]]; then - local host_path="${BASH_REMATCH[1]}" - local container_path="${BASH_REMATCH[2]}" - - echo "DEBUG: Found mount: $host_path -> $container_path" >&2 - - # Skip ONLY system caches and configs, NOT user dotfiles - if [[ "$container_path" =~ (/root/\.cache|/home/developer/\.cache|/tmp|cache|\.npm|\.pip|\.yarn) ]]; then - echo "DEBUG: Skipping system mount: $container_path" >&2 - continue - fi - - # Expand environment variables for display - local display_host_path="$host_path" - if [[ "$host_path" =~ ^\$HOME ]]; then - display_host_path="${host_path/\$HOME/$HOME}" - fi - - # Store mount data for potential removal - mounts_data+=("$host_path:$container_path") - - # Show numbered list if requested - if [[ "$show_numbers" == "true" ]]; then - printf "${YELLOW}%2d.${NC} " "$counter" - else - printf " ${PURPLE}โ€ข${NC} " - fi - - printf "${GREEN}Host:${NC} %s\n" "$display_host_path" - printf " ${CYAN}โ†’${NC} Container: %s\n" "$container_path" - - # Check if directory exists - if [[ -d "$display_host_path" ]]; then - printf " ${BLUE}Status:${NC} ${GREEN}โœ… Exists${NC}\n" - else - printf " ${BLUE}Status:${NC} ${RED}โŒ Missing${NC}\n" - fi - printf "\n" - - counter=$((counter + 1)) - mounts_found=true - fi - done < docker-compose.yml - - if [[ "$mounts_found" != "true" ]]; then - printf " ${GRAY}No custom directory mounts configured${NC}\n" - printf "\n" - fi - - printf "โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”\n" - - # Export mounts data for removal function - export CURRENT_MOUNTS_DATA="${mounts_data[*]}" - echo "DEBUG: Total mounts found: $((counter - 1))" >&2 - echo "DEBUG: Mounts data: $CURRENT_MOUNTS_DATA" >&2 - return $((counter - 1)) # Return total count -} - -echo "Testing get_current_mounts with show_numbers=true" -get_current_mounts_test "true" diff --git a/test_mounts.sh b/test_mounts.sh deleted file mode 100644 index 0769b98..0000000 --- a/test_mounts.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash - -# Test file for get_current_mounts function -source scripts/configure.sh - -# Skip main execution by overriding it -main() { - echo "Testing get_current_mounts function..." - get_current_mounts "true" -} - -main From c213c2f853bc2abee2e3b7fb205fe2f70de3043f Mon Sep 17 00:00:00 2001 From: Ricardo <31641216+manghidev@users.noreply.github.com> Date: Wed, 2 Jul 2025 15:28:22 -0600 Subject: [PATCH 14/20] refactor: remove LazyVim Docker configuration file to streamline codebase --- .lazyvim-docker-config | 6 ------ 1 file changed, 6 deletions(-) delete mode 100644 .lazyvim-docker-config diff --git a/.lazyvim-docker-config b/.lazyvim-docker-config deleted file mode 100644 index 173c3b0..0000000 --- a/.lazyvim-docker-config +++ /dev/null @@ -1,6 +0,0 @@ -# LazyVim Docker Configuration - Auto-generated -# Last updated: Wed Jul 2 11:06:39 CST 2025 -DOCUMENTS_DECISION="no" -PROJECTS_DECISION="no" -PROJECTS_PATH="" -LAST_TIMEZONE="America/Mexico_City" From 11a90c323b651f7c8d76c55d529f9f22e4829478 Mon Sep 17 00:00:00 2001 From: Ricardo <31641216+manghidev@users.noreply.github.com> Date: Wed, 2 Jul 2025 16:47:41 -0600 Subject: [PATCH 15/20] fix: improve user prompts and output formatting in uninstall and update scripts --- scripts/remote-uninstall.sh | 22 ++++++--- scripts/remote-update.sh | 2 +- scripts/start.sh | 69 ++++++++++++++++++++-------- scripts/uninstall-global-commands.sh | 6 ++- 4 files changed, 72 insertions(+), 27 deletions(-) diff --git a/scripts/remote-uninstall.sh b/scripts/remote-uninstall.sh index c125ba4..af5cf1e 100755 --- a/scripts/remote-uninstall.sh +++ b/scripts/remote-uninstall.sh @@ -77,11 +77,11 @@ EOF echo "" print_warning "๐Ÿงน To complete cleanup and remove any traces:" echo "" - echo " ${GREEN}Option 1 (Easiest):${NC}" - echo " ${GREEN}$helper_script${NC}" + printf " ${GREEN}Option 1 (Easiest):${NC}\n" + printf " ${GREEN}%s${NC}\n" "$helper_script" echo "" - echo " ${GREEN}Option 2 (Manual):${NC}" - echo " ${GREEN}exec $current_shell${NC}" + printf " ${GREEN}Option 2 (Manual):${NC}\n" + printf " ${GREEN}exec %s${NC}\n" "$current_shell" echo "" # Try to detect if we can restart directly @@ -203,7 +203,11 @@ remove_global_command() { remove_path_modifications() { echo "" printf "Do you want to remove PATH modifications from shell config? [y/N]: " - read -r response /dev/null || true + + # Pull latest base images + print_info "Pulling latest base images..." + docker compose pull 2>/dev/null || print_warning "Could not pull some images, continuing..." + + # Build the container + print_info "Building container..." + if docker compose build --no-cache 2>/dev/null; then + print_success "Container built successfully" + + # Start the container + print_info "Starting the container..." + if docker compose up --force-recreate -d 2>/dev/null; then + print_success "Container started successfully" + + # Wait for container to be ready + print_info "Waiting for container to be ready..." + sleep 3 + + # Check if container is running + if docker compose ps 2>/dev/null | grep -q "Up"; then + print_success "Container is running!" + print_info "Opening shell in the container..." + # Don't try to open shell automatically - let user do it manually + print_info "You can enter the container with: lazy enter" + else + print_warning "Container may not have started properly. Check with 'lazy status'" + fi + else + print_warning "Failed to start container. You can try 'lazy start' later." + fi else print_warning "Docker build failed, but installation completed. You can run 'lazy build' later." fi @@ -363,17 +396,17 @@ main() { echo " โ€ข Projects: Auto-mounted if exists" echo "" print_info "Usage:" - echo " ${GREEN}lazy enter${NC} # Enter LazyVim development environment" - echo " ${GREEN}lazy start${NC} # Start the container" - echo " ${GREEN}lazy stop${NC} # Stop the container" - echo " ${GREEN}lazy status${NC} # Check container status" - echo " ${GREEN}lazy configure${NC} # Reconfigure directories and timezone" - echo " ${GREEN}lazy update${NC} # Update to latest version" - echo " ${GREEN}lazy uninstall${NC} # Uninstall everything" - echo " ${GREEN}lazy help${NC} # Show all available commands" + printf " ${GREEN}lazy enter${NC} # Enter LazyVim development environment\n" + printf " ${GREEN}lazy start${NC} # Start the container\n" + printf " ${GREEN}lazy stop${NC} # Stop the container\n" + printf " ${GREEN}lazy status${NC} # Check container status\n" + printf " ${GREEN}lazy configure${NC} # Reconfigure directories and timezone\n" + printf " ${GREEN}lazy update${NC} # Update to latest version\n" + printf " ${GREEN}lazy uninstall${NC} # Uninstall everything\n" + printf " ${GREEN}lazy help${NC} # Show all available commands\n" echo "" print_info "To customize configuration later:" - echo " Run: ${GREEN}lazy configure${NC}" + printf " Run: ${GREEN}lazy configure${NC}\n" echo "" print_info "Happy coding! ๐Ÿš€" echo "" diff --git a/scripts/uninstall-global-commands.sh b/scripts/uninstall-global-commands.sh index 2219f5e..5f9dd06 100755 --- a/scripts/uninstall-global-commands.sh +++ b/scripts/uninstall-global-commands.sh @@ -110,7 +110,11 @@ remove_project_directory() { print_status "Current project directory: $project_dir" echo printf "Do you want to remove the entire LazyVim Docker project directory? [y/N]: " - read -r response Date: Thu, 3 Jul 2025 09:47:16 -0600 Subject: [PATCH 16/20] feat: enhance remote uninstall script with interactive prompts and force options --- README.md | 16 +++- scripts/remote-uninstall.sh | 179 +++++++++++++++++++++++++++--------- 2 files changed, 148 insertions(+), 47 deletions(-) diff --git a/README.md b/README.md index e51140c..a36a023 100644 --- a/README.md +++ b/README.md @@ -123,11 +123,17 @@ curl -fsSL https://raw.githubusercontent.com/manghidev/lazyvim-docker/main/scrip **`remote-uninstall.sh`** - Complete cleanup ```bash -# Uninstall everything with prompts +# Interactive uninstall with prompts lazy uninstall -# Or run directly +# Or run directly with prompts curl -fsSL https://raw.githubusercontent.com/manghidev/lazyvim-docker/main/scripts/remote-uninstall.sh | bash + +# Force uninstall without prompts (CI/automation) +curl -fsSL https://raw.githubusercontent.com/manghidev/lazyvim-docker/main/scripts/remote-uninstall.sh | LAZYVIM_FORCE_UNINSTALL=true bash + +# Force uninstall with PATH cleanup +curl -fsSL https://raw.githubusercontent.com/manghidev/lazyvim-docker/main/scripts/remote-uninstall.sh | LAZYVIM_FORCE_UNINSTALL=true LAZYVIM_REMOVE_PATH=true bash ``` **What it does:** @@ -136,7 +142,11 @@ curl -fsSL https://raw.githubusercontent.com/manghidev/lazyvim-docker/main/scrip - โœ… Removes global `lazy` command - โœ… Optionally cleans PATH modifications from shell configs - โœ… Creates backups before making changes -- โœ… Interactive prompts for safety +- โœ… Interactive prompts for safety (or force mode for automation) + +**Environment Variables:** +- `LAZYVIM_FORCE_UNINSTALL=true` - Skip confirmation prompts +- `LAZYVIM_REMOVE_PATH=true` - Automatically remove PATH modifications --- diff --git a/scripts/remote-uninstall.sh b/scripts/remote-uninstall.sh index af5cf1e..d50d18b 100755 --- a/scripts/remote-uninstall.sh +++ b/scripts/remote-uninstall.sh @@ -5,14 +5,24 @@ set -e -# Colors for output -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -BLUE='\033[0;34m' -PURPLE='\033[0;35m' -CYAN='\033[0;36m' -NC='\033[0m' # No Color +# Colors for output using tput (more compatible) +if command -v tput >/dev/null 2>&1 && [[ -t 1 ]]; then + RED=$(tput setaf 1 2>/dev/null || echo '') + GREEN=$(tput setaf 2 2>/dev/null || echo '') + YELLOW=$(tput setaf 3 2>/dev/null || echo '') + BLUE=$(tput setaf 4 2>/dev/null || echo '') + PURPLE=$(tput setaf 5 2>/dev/null || echo '') + CYAN=$(tput setaf 6 2>/dev/null || echo '') + NC=$(tput sgr0 2>/dev/null || echo '') +else + RED='' + GREEN='' + YELLOW='' + BLUE='' + PURPLE='' + CYAN='' + NC='' +fi # Configuration INSTALL_DIR="$HOME/.local/share/lazyvim-docker" @@ -84,21 +94,26 @@ EOF printf " ${GREEN}exec %s${NC}\n" "$current_shell" echo "" - # Try to detect if we can restart directly - if [[ -t 0 ]] && [[ -t 1 ]] && [[ $- == *i* ]]; then + # Check if we can actually read from terminal (not piped) + if [[ -t 0 ]] && [[ -t 1 ]] && [[ ! -p /dev/stdin ]]; then + # Interactive mode - try to read from terminal directly print_info "โœจ Auto-cleanup available!" - local choice printf "Press ENTER to restart now, or 'n' to skip cleanup: " - read -r choice - - if [[ "$choice" != "n" ]] && [[ "$choice" != "N" ]]; then - print_info "Restarting terminal for clean environment..." - exec "$current_shell" + local choice + if read -r choice < /dev/tty 2>/dev/null; then + if [[ "$choice" != "n" ]] && [[ "$choice" != "N" ]]; then + print_info "Restarting terminal for clean environment..." + exec "$current_shell" + else + print_info "Cleanup skipped - environment may show command traces" + fi else - print_info "Cleanup skipped - environment may show command traces" + print_info "๐Ÿ’ก Copy and paste the first command to clean your terminal" + print_info "This ensures no traces of 'lazy' commands remain" fi else - print_info "๏ฟฝ Copy and paste the first command to clean your terminal" + # Non-interactive mode (piped or redirected) + print_info "๐Ÿ’ก Copy and paste the first command to clean your terminal" print_info "This ensures no traces of 'lazy' commands remain" fi } @@ -202,15 +217,65 @@ remove_global_command() { # Remove PATH modifications (optional) remove_path_modifications() { echo "" - printf "Do you want to remove PATH modifications from shell config? [y/N]: " - if [[ -t 0 ]] && [[ -t 1 ]] && [[ $- == *i* ]]; then - read -r response /dev/null; then + # Successfully read from terminal + case "$response" in + [yY][eE][sS]|[yY]) + print_step "Removing PATH modifications..." + + local shell_configs=("$HOME/.zshrc" "$HOME/.bashrc" "$HOME/.bash_profile") + + for config in "${shell_configs[@]}"; do + if [ -f "$config" ]; then + # Create backup + cp "$config" "${config}.backup.$(date +%Y%m%d-%H%M%S)" + + # Remove LazyVim Docker PATH modifications + sed -i.tmp '/# LazyVim Docker - Add local bin to PATH/d' "$config" 2>/dev/null || true + sed -i.tmp '/export PATH=.*\.local\/bin.*PATH/d' "$config" 2>/dev/null || true + rm -f "${config}.tmp" + + print_info "Cleaned PATH modifications from: $config" + fi + done + + print_success "PATH modifications removed" + ;; + *) + print_info "PATH modifications preserved" + ;; + esac + else + # Failed to read from terminal - treat as non-interactive + if [[ "${LAZYVIM_REMOVE_PATH:-}" == "true" ]]; then + print_info "Non-interactive mode: removing PATH modifications (LAZYVIM_REMOVE_PATH=true)" + # Remove PATH logic here... + print_step "Removing PATH modifications..." + local shell_configs=("$HOME/.zshrc" "$HOME/.bashrc" "$HOME/.bash_profile") + for config in "${shell_configs[@]}"; do + if [ -f "$config" ]; then + cp "$config" "${config}.backup.$(date +%Y%m%d-%H%M%S)" + sed -i.tmp '/# LazyVim Docker - Add local bin to PATH/d' "$config" 2>/dev/null || true + sed -i.tmp '/export PATH=.*\.local\/bin.*PATH/d' "$config" 2>/dev/null || true + rm -f "${config}.tmp" + print_info "Cleaned PATH modifications from: $config" + fi + done + print_success "PATH modifications removed" + else + print_info "Non-interactive mode: keeping PATH modifications" + fi + fi + else + # Non-interactive mode (piped or redirected) + if [[ "${LAZYVIM_REMOVE_PATH:-}" == "true" ]]; then + print_info "Non-interactive mode: removing PATH modifications (LAZYVIM_REMOVE_PATH=true)" print_step "Removing PATH modifications..." local shell_configs=("$HOME/.zshrc" "$HOME/.bashrc" "$HOME/.bash_profile") @@ -230,11 +295,10 @@ remove_path_modifications() { done print_success "PATH modifications removed" - ;; - *) - print_info "PATH modifications preserved" - ;; - esac + else + print_info "Non-interactive mode: keeping PATH modifications" + fi + fi } # Confirm uninstallation @@ -246,22 +310,49 @@ confirm_uninstall() { echo " โ€ข Global 'lazy' command" echo " โ€ข All data and configurations" echo "" - printf "Are you sure you want to continue? [y/N]: " - if [[ -t 0 ]] && [[ -t 1 ]] && [[ $- == *i* ]]; then - read -r response /dev/null; then + # Successfully read from terminal + case "$response" in + [yY][eE][sS]|[yY]) + return 0 + ;; + *) + print_info "Uninstallation cancelled" + exit 0 + ;; + esac + else + # Failed to read from terminal - treat as non-interactive + print_info "Cannot read from terminal - treating as non-interactive" + if [[ "${LAZYVIM_FORCE_UNINSTALL:-}" == "true" ]]; then + print_info "Proceeding with forced uninstall (LAZYVIM_FORCE_UNINSTALL=true)" + return 0 + else + print_info "Uninstallation cancelled - to force, set: LAZYVIM_FORCE_UNINSTALL=true" + exit 0 + fi + fi + else + # Non-interactive mode (piped or redirected) + if [[ "${LAZYVIM_FORCE_UNINSTALL:-}" == "true" ]]; then + print_info "Non-interactive mode: proceeding with forced uninstall (LAZYVIM_FORCE_UNINSTALL=true)" return 0 - ;; - *) - print_info "Uninstallation cancelled" + else + print_info "Non-interactive mode: uninstallation cancelled for safety" + print_info "To force uninstall via pipe, set: LAZYVIM_FORCE_UNINSTALL=true" + print_info "" + print_info "Examples:" + printf " ${GREEN}LAZYVIM_FORCE_UNINSTALL=true curl -fsSL [URL] | bash${NC}\n" + printf " ${GREEN}curl -fsSL [URL] | LAZYVIM_FORCE_UNINSTALL=true bash${NC}\n" exit 0 - ;; - esac + fi + fi } # Main uninstallation process From e0f99ede73691029f45e707d521f526df00d22a9 Mon Sep 17 00:00:00 2001 From: Ricardo <31641216+manghidev@users.noreply.github.com> Date: Thu, 3 Jul 2025 10:11:26 -0600 Subject: [PATCH 17/20] refactor: streamline uninstallation script by removing interactive prompts and enhancing automatic path modifications --- scripts/remote-uninstall.sh | 180 ++++++++++-------------------------- 1 file changed, 49 insertions(+), 131 deletions(-) diff --git a/scripts/remote-uninstall.sh b/scripts/remote-uninstall.sh index d50d18b..154cdb1 100755 --- a/scripts/remote-uninstall.sh +++ b/scripts/remote-uninstall.sh @@ -93,29 +93,8 @@ EOF printf " ${GREEN}Option 2 (Manual):${NC}\n" printf " ${GREEN}exec %s${NC}\n" "$current_shell" echo "" - - # Check if we can actually read from terminal (not piped) - if [[ -t 0 ]] && [[ -t 1 ]] && [[ ! -p /dev/stdin ]]; then - # Interactive mode - try to read from terminal directly - print_info "โœจ Auto-cleanup available!" - printf "Press ENTER to restart now, or 'n' to skip cleanup: " - local choice - if read -r choice < /dev/tty 2>/dev/null; then - if [[ "$choice" != "n" ]] && [[ "$choice" != "N" ]]; then - print_info "Restarting terminal for clean environment..." - exec "$current_shell" - else - print_info "Cleanup skipped - environment may show command traces" - fi - else - print_info "๐Ÿ’ก Copy and paste the first command to clean your terminal" - print_info "This ensures no traces of 'lazy' commands remain" - fi - else - # Non-interactive mode (piped or redirected) - print_info "๐Ÿ’ก Copy and paste the first command to clean your terminal" - print_info "This ensures no traces of 'lazy' commands remain" - fi + print_info "๐Ÿ’ก Copy and paste the first command to clean your terminal" + print_info "This ensures no traces of 'lazy' commands remain" } # Stop and remove Docker containers @@ -214,93 +193,38 @@ remove_global_command() { fi } -# Remove PATH modifications (optional) +# Remove PATH modifications automatically remove_path_modifications() { - echo "" + print_step "Removing PATH modifications..." - # Check if we can actually read from terminal (not piped) - if [[ -t 0 ]] && [[ -t 1 ]] && [[ ! -p /dev/stdin ]]; then - # Interactive mode - try to read from terminal directly - printf "Do you want to remove PATH modifications from shell config? [y/N]: " - local response - if read -r response < /dev/tty 2>/dev/null; then - # Successfully read from terminal - case "$response" in - [yY][eE][sS]|[yY]) - print_step "Removing PATH modifications..." - - local shell_configs=("$HOME/.zshrc" "$HOME/.bashrc" "$HOME/.bash_profile") - - for config in "${shell_configs[@]}"; do - if [ -f "$config" ]; then - # Create backup - cp "$config" "${config}.backup.$(date +%Y%m%d-%H%M%S)" - - # Remove LazyVim Docker PATH modifications - sed -i.tmp '/# LazyVim Docker - Add local bin to PATH/d' "$config" 2>/dev/null || true - sed -i.tmp '/export PATH=.*\.local\/bin.*PATH/d' "$config" 2>/dev/null || true - rm -f "${config}.tmp" - - print_info "Cleaned PATH modifications from: $config" - fi - done - - print_success "PATH modifications removed" - ;; - *) - print_info "PATH modifications preserved" - ;; - esac - else - # Failed to read from terminal - treat as non-interactive - if [[ "${LAZYVIM_REMOVE_PATH:-}" == "true" ]]; then - print_info "Non-interactive mode: removing PATH modifications (LAZYVIM_REMOVE_PATH=true)" - # Remove PATH logic here... - print_step "Removing PATH modifications..." - local shell_configs=("$HOME/.zshrc" "$HOME/.bashrc" "$HOME/.bash_profile") - for config in "${shell_configs[@]}"; do - if [ -f "$config" ]; then - cp "$config" "${config}.backup.$(date +%Y%m%d-%H%M%S)" - sed -i.tmp '/# LazyVim Docker - Add local bin to PATH/d' "$config" 2>/dev/null || true - sed -i.tmp '/export PATH=.*\.local\/bin.*PATH/d' "$config" 2>/dev/null || true - rm -f "${config}.tmp" - print_info "Cleaned PATH modifications from: $config" - fi - done - print_success "PATH modifications removed" - else - print_info "Non-interactive mode: keeping PATH modifications" + local shell_configs=("$HOME/.zshrc" "$HOME/.bashrc" "$HOME/.bash_profile") + local removed_any=false + + for config in "${shell_configs[@]}"; do + if [ -f "$config" ]; then + # Create backup + cp "$config" "${config}.backup.$(date +%Y%m%d-%H%M%S)" + + # Remove LazyVim Docker PATH modifications + if grep -q "LazyVim Docker" "$config" 2>/dev/null; then + sed -i.tmp '/# LazyVim Docker - Add local bin to PATH/d' "$config" 2>/dev/null || true + sed -i.tmp '/export PATH=.*\.local\/bin.*PATH/d' "$config" 2>/dev/null || true + rm -f "${config}.tmp" + + print_info "Cleaned PATH modifications from: $config" + removed_any=true fi fi + done + + if [[ "$removed_any" == true ]]; then + print_success "PATH modifications removed" else - # Non-interactive mode (piped or redirected) - if [[ "${LAZYVIM_REMOVE_PATH:-}" == "true" ]]; then - print_info "Non-interactive mode: removing PATH modifications (LAZYVIM_REMOVE_PATH=true)" - print_step "Removing PATH modifications..." - - local shell_configs=("$HOME/.zshrc" "$HOME/.bashrc" "$HOME/.bash_profile") - - for config in "${shell_configs[@]}"; do - if [ -f "$config" ]; then - # Create backup - cp "$config" "${config}.backup.$(date +%Y%m%d-%H%M%S)" - - # Remove LazyVim Docker PATH modifications - sed -i.tmp '/# LazyVim Docker - Add local bin to PATH/d' "$config" 2>/dev/null || true - sed -i.tmp '/export PATH=.*\.local\/bin.*PATH/d' "$config" 2>/dev/null || true - rm -f "${config}.tmp" - - print_info "Cleaned PATH modifications from: $config" - fi - done - - print_success "PATH modifications removed" - else - print_info "Non-interactive mode: keeping PATH modifications" - fi + print_info "No PATH modifications found" fi } +# Confirm uninstallation # Confirm uninstallation confirm_uninstall() { echo "" @@ -311,38 +235,22 @@ confirm_uninstall() { echo " โ€ข All data and configurations" echo "" - # Check if we can actually read from terminal (not piped) - if [[ -t 0 ]] && [[ -t 1 ]] && [[ ! -p /dev/stdin ]]; then - # Interactive mode - try to read from terminal directly - printf "Are you sure you want to continue? [y/N]: " - local response - if read -r response < /dev/tty 2>/dev/null; then - # Successfully read from terminal - case "$response" in - [yY][eE][sS]|[yY]) - return 0 - ;; - *) - print_info "Uninstallation cancelled" - exit 0 - ;; - esac - else - # Failed to read from terminal - treat as non-interactive - print_info "Cannot read from terminal - treating as non-interactive" - if [[ "${LAZYVIM_FORCE_UNINSTALL:-}" == "true" ]]; then - print_info "Proceeding with forced uninstall (LAZYVIM_FORCE_UNINSTALL=true)" - return 0 - else - print_info "Uninstallation cancelled - to force, set: LAZYVIM_FORCE_UNINSTALL=true" - exit 0 - fi - fi + # Try to read from terminal, fallback to stdin if needed + printf "Are you sure you want to continue? [y/N]: " + local response + + # Try multiple methods to read input + if read -r response < /dev/tty 2>/dev/null; then + # Successfully read from terminal + : + elif [[ -t 0 ]]; then + # stdin is a terminal, try regular read + read -r response else - # Non-interactive mode (piped or redirected) + # Non-interactive mode or piped input if [[ "${LAZYVIM_FORCE_UNINSTALL:-}" == "true" ]]; then print_info "Non-interactive mode: proceeding with forced uninstall (LAZYVIM_FORCE_UNINSTALL=true)" - return 0 + response="y" else print_info "Non-interactive mode: uninstallation cancelled for safety" print_info "To force uninstall via pipe, set: LAZYVIM_FORCE_UNINSTALL=true" @@ -353,6 +261,16 @@ confirm_uninstall() { exit 0 fi fi + + case "$response" in + [yY][eE][sS]|[yY]) + return 0 + ;; + *) + print_info "Uninstallation cancelled" + exit 0 + ;; + esac } # Main uninstallation process From ad3fdba50983c52f532fc0175e448e17596085ba Mon Sep 17 00:00:00 2001 From: Ricardo <31641216+manghidev@users.noreply.github.com> Date: Thu, 3 Jul 2025 10:15:11 -0600 Subject: [PATCH 18/20] docs: enhance uninstallation section with detailed instructions and safety features --- README.md | 104 ++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 70 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index a36a023..0adee2f 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,22 @@ make build # Build the environment make enter # Enter the container ``` +### ๐Ÿ—‘๏ธ Uninstallation +Complete removal when you no longer need LazyVim Docker: + +```bash +# Interactive uninstall (asks for confirmation) +lazy uninstall + +# Or run directly +curl -fsSL https://raw.githubusercontent.com/manghidev/lazyvim-docker/main/scripts/remote-uninstall.sh | bash + +# Automated uninstall (no prompts - for scripts/CI) +LAZYVIM_FORCE_UNINSTALL=true curl -fsSL https://raw.githubusercontent.com/manghidev/lazyvim-docker/main/scripts/remote-uninstall.sh | bash +``` + +**Removes everything**: Docker containers, installation files, global commands, and shell configurations in one step. + --- ## โœจ Features @@ -120,33 +136,36 @@ curl -fsSL https://raw.githubusercontent.com/manghidev/lazyvim-docker/main/scrip - โœ… Optionally rebuilds Docker containers ### ๐Ÿ—‘๏ธ Uninstallation Script -**`remote-uninstall.sh`** - Complete cleanup +**`remote-uninstall.sh`** - Complete and safe cleanup ```bash -# Interactive uninstall with prompts +# Interactive uninstall with confirmation prompt lazy uninstall # Or run directly with prompts curl -fsSL https://raw.githubusercontent.com/manghidev/lazyvim-docker/main/scripts/remote-uninstall.sh | bash -# Force uninstall without prompts (CI/automation) -curl -fsSL https://raw.githubusercontent.com/manghidev/lazyvim-docker/main/scripts/remote-uninstall.sh | LAZYVIM_FORCE_UNINSTALL=true bash - -# Force uninstall with PATH cleanup -curl -fsSL https://raw.githubusercontent.com/manghidev/lazyvim-docker/main/scripts/remote-uninstall.sh | LAZYVIM_FORCE_UNINSTALL=true LAZYVIM_REMOVE_PATH=true bash +# Force uninstall without prompts (for automation/CI) +LAZYVIM_FORCE_UNINSTALL=true curl -fsSL https://raw.githubusercontent.com/manghidev/lazyvim-docker/main/scripts/remote-uninstall.sh | bash ``` -**What it does:** -- โœ… Stops and removes Docker containers/images -- โœ… Removes installation directory (`~/.local/share/lazyvim-docker`) +**What it does when you confirm:** +- โœ… Stops and removes all Docker containers and images +- โœ… Removes installation directory (`~/.local/share/lazyvim-docker`) - โœ… Removes global `lazy` command -- โœ… Optionally cleans PATH modifications from shell configs -- โœ… Creates backups before making changes -- โœ… Interactive prompts for safety (or force mode for automation) +- โœ… Removes shell configuration entries (`.zshrc`, `.bashrc`, etc.) +- โœ… Removes PATH modifications automatically +- โœ… Creates timestamped backups before making changes +- โœ… **Everything is removed in one confirmation** - no additional prompts + +**Safety Features:** +- ๐Ÿ›ก๏ธ **Interactive confirmation** - Shows exactly what will be removed +- ๐Ÿ›ก๏ธ **Non-interactive safety** - Cancels by default when piped unless forced +- ๐Ÿ›ก๏ธ **Automatic backups** - Creates backups of modified configuration files +- ๐Ÿ›ก๏ธ **Clear messaging** - Shows progress and results of each step **Environment Variables:** -- `LAZYVIM_FORCE_UNINSTALL=true` - Skip confirmation prompts -- `LAZYVIM_REMOVE_PATH=true` - Automatically remove PATH modifications +- `LAZYVIM_FORCE_UNINSTALL=true` - Force uninstall without confirmation (for automation) --- @@ -196,26 +215,28 @@ curl -fsSL https://raw.githubusercontent.com/manghidev/lazyvim-docker/main/scrip - Backup created before update in `~/.local/share/lazyvim-docker-backup-[timestamp]` ### ๐Ÿ—‘๏ธ remote-uninstall.sh -**Purpose**: Complete removal of LazyVim Docker installation +**Purpose**: Complete and safe removal of LazyVim Docker installation **Removal Process:** -1. Stops all running containers -2. Removes Docker containers and images -3. Removes Docker volumes -4. Removes installation directory -5. Removes global `lazy` command -6. Optionally cleans PATH from shell configs -7. Creates backups before deletion - -**Interactive Prompts:** -- Confirm complete uninstall -- Choose to remove PATH modifications -- Option to keep or remove project files - -**Cleanup Scope:** -- Docker: containers, images, volumes -- Files: installation directory, global command -- Config: PATH modifications (optional) +1. Shows exactly what will be removed +2. **Single confirmation prompt** - no additional questions +3. Stops all running containers +4. Removes Docker containers, images, and volumes +5. Removes installation directory (`~/.local/share/lazyvim-docker`) +6. Removes global `lazy` command and shell integrations +7. Removes PATH modifications automatically +8. Creates timestamped backups before any changes + +**Smart Detection:** +- **Interactive mode**: Shows confirmation prompt when run manually +- **Non-interactive mode**: Safely cancels when piped unless forced with `LAZYVIM_FORCE_UNINSTALL=true` +- **Automatic backup**: Creates `.backup.[timestamp]` files before modifying shell configs + +**Complete Cleanup:** +- โœ… Docker: containers, images, volumes +- โœ… Files: installation directory, global command +- โœ… Config: shell entries and PATH modifications +- โœ… **Everything removed in one confirmation** - streamlined process --- @@ -375,10 +396,25 @@ lazy build # Update to fix issues lazy update -# Nuclear option +# Nuclear option - complete reinstall lazy uninstall && curl -fsSL https://raw.githubusercontent.com/manghidev/lazyvim-docker/main/scripts/start.sh | bash ``` +### Uninstallation Issues +```bash +# Script hangs when run via curl/pipe +LAZYVIM_FORCE_UNINSTALL=true curl -fsSL https://raw.githubusercontent.com/manghidev/lazyvim-docker/main/scripts/remote-uninstall.sh | bash + +# Manual cleanup if script fails +docker stop lazyvim 2>/dev/null || true +docker rm lazyvim 2>/dev/null || true +rm -rf ~/.local/share/lazyvim-docker +rm -f ~/.local/bin/lazy + +# Clean terminal after uninstall +exec $SHELL +``` + --- ## ๐Ÿ“‘ Documentation & Support From f6f75c81900c896403a83890efac3f29b54fc7d1 Mon Sep 17 00:00:00 2001 From: Ricardo <31641216+manghidev@users.noreply.github.com> Date: Thu, 3 Jul 2025 10:23:45 -0600 Subject: [PATCH 19/20] fix: enhance existence checks for mounted directories and provide helpful info for missing dotfiles --- scripts/configure.sh | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/scripts/configure.sh b/scripts/configure.sh index 8bab0d3..5debaba 100755 --- a/scripts/configure.sh +++ b/scripts/configure.sh @@ -164,11 +164,24 @@ get_current_mounts() { printf "${GREEN}Host:${NC} %s\n" "$display_host_path" printf " ${CYAN}โ†’${NC} Container: %s\n" "$container_path" - # Check if directory exists - if [[ -d "$display_host_path" ]]; then - printf " ${BLUE}Status:${NC} ${GREEN}โœ… Exists${NC}\n" + # Check if directory or file exists + if [[ -e "$display_host_path" ]]; then + if [[ -d "$display_host_path" ]]; then + printf " ${BLUE}Status:${NC} ${GREEN}โœ… Directory Exists${NC}\n" + elif [[ -f "$display_host_path" ]]; then + printf " ${BLUE}Status:${NC} ${GREEN}โœ… File Exists${NC}\n" + else + printf " ${BLUE}Status:${NC} ${GREEN}โœ… Exists${NC}\n" + fi else - printf " ${BLUE}Status:${NC} ${RED}โŒ Missing${NC}\n" + # For dotfiles that are created by the container, provide helpful info + if [[ "$display_host_path" =~ \.dotfiles/\.(zshrc|p10k\.zsh)$ ]]; then + printf " ${BLUE}Status:${NC} ${YELLOW}โšก Will be auto-created on first run${NC}\n" + elif [[ "$display_host_path" =~ \.dotfiles/\.config/(nvim|lazygit)$ ]]; then + printf " ${BLUE}Status:${NC} ${YELLOW}โšก Will be auto-created with configs${NC}\n" + else + printf " ${BLUE}Status:${NC} ${RED}โŒ Missing${NC}\n" + fi fi printf "\n" From bde31dd52673b0da0c1ee48b90884e5aed40d7e9 Mon Sep 17 00:00:00 2001 From: Ricardo <31641216+manghidev@users.noreply.github.com> Date: Thu, 3 Jul 2025 10:32:44 -0600 Subject: [PATCH 20/20] fix: remove redundant force uninstall instructions from README and clarify uninstallation process --- README.md | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/README.md b/README.md index 0adee2f..6b99c93 100644 --- a/README.md +++ b/README.md @@ -41,9 +41,6 @@ lazy uninstall # Or run directly curl -fsSL https://raw.githubusercontent.com/manghidev/lazyvim-docker/main/scripts/remote-uninstall.sh | bash - -# Automated uninstall (no prompts - for scripts/CI) -LAZYVIM_FORCE_UNINSTALL=true curl -fsSL https://raw.githubusercontent.com/manghidev/lazyvim-docker/main/scripts/remote-uninstall.sh | bash ``` **Removes everything**: Docker containers, installation files, global commands, and shell configurations in one step. @@ -144,9 +141,6 @@ lazy uninstall # Or run directly with prompts curl -fsSL https://raw.githubusercontent.com/manghidev/lazyvim-docker/main/scripts/remote-uninstall.sh | bash - -# Force uninstall without prompts (for automation/CI) -LAZYVIM_FORCE_UNINSTALL=true curl -fsSL https://raw.githubusercontent.com/manghidev/lazyvim-docker/main/scripts/remote-uninstall.sh | bash ``` **What it does when you confirm:** @@ -164,9 +158,6 @@ LAZYVIM_FORCE_UNINSTALL=true curl -fsSL https://raw.githubusercontent.com/manghi - ๐Ÿ›ก๏ธ **Automatic backups** - Creates backups of modified configuration files - ๐Ÿ›ก๏ธ **Clear messaging** - Shows progress and results of each step -**Environment Variables:** -- `LAZYVIM_FORCE_UNINSTALL=true` - Force uninstall without confirmation (for automation) - --- ## ๐Ÿ”ฌ Script Details & Technical Info @@ -229,7 +220,6 @@ LAZYVIM_FORCE_UNINSTALL=true curl -fsSL https://raw.githubusercontent.com/manghi **Smart Detection:** - **Interactive mode**: Shows confirmation prompt when run manually -- **Non-interactive mode**: Safely cancels when piped unless forced with `LAZYVIM_FORCE_UNINSTALL=true` - **Automatic backup**: Creates `.backup.[timestamp]` files before modifying shell configs **Complete Cleanup:** @@ -400,21 +390,6 @@ lazy update lazy uninstall && curl -fsSL https://raw.githubusercontent.com/manghidev/lazyvim-docker/main/scripts/start.sh | bash ``` -### Uninstallation Issues -```bash -# Script hangs when run via curl/pipe -LAZYVIM_FORCE_UNINSTALL=true curl -fsSL https://raw.githubusercontent.com/manghidev/lazyvim-docker/main/scripts/remote-uninstall.sh | bash - -# Manual cleanup if script fails -docker stop lazyvim 2>/dev/null || true -docker rm lazyvim 2>/dev/null || true -rm -rf ~/.local/share/lazyvim-docker -rm -f ~/.local/bin/lazy - -# Clean terminal after uninstall -exec $SHELL -``` - --- ## ๐Ÿ“‘ Documentation & Support