From e3041b755b3b5d209a814af3b7b21c60ecc4e5db Mon Sep 17 00:00:00 2001 From: Aditya Gupta Date: Fri, 19 Jun 2026 23:52:58 +0530 Subject: [PATCH] feat: Tab Autocompletion --- b.sh | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++ bootstrap.sh | 23 +++++++++++++++++---- 2 files changed, 77 insertions(+), 4 deletions(-) diff --git a/b.sh b/b.sh index a3e8668..7905f90 100755 --- a/b.sh +++ b/b.sh @@ -38,4 +38,62 @@ b() { # Execute the routes file bash "$routes_file" "$@" } + +# Autocompletion for the b command in Bash +_b_completion() { + local cur prev opts + COMPREPLY=() + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + + # If completing the first argument after 'b' + if [ "$COMP_CWORD" -eq 1 ]; then + opts="all conf bye" + + local routes_file="$HOME/.config/bootstrap/routes.sh" + if [ -f "$routes_file" ]; then + # Extract installer keys dynamically from the routes.sh file + local installer_keys + installer_keys=$(grep -E "^INSTALLER_KEYS=" "$routes_file" 2>/dev/null | sed -E 's/INSTALLER_KEYS=\(([^)]+)\)/\1/' 2>/dev/null) + if [ -n "$installer_keys" ]; then + opts="$opts $installer_keys" + fi + fi + + # Support comma-separated completions (e.g. b nvim,ya) + if [[ "$cur" == *,* ]]; then + local prefix="${cur%,*}" + local last="${cur##*,}" + local matches + matches=$(compgen -W "$opts" -- "$last") + if [ -n "$matches" ]; then + COMPREPLY=() + for m in $matches; do + # Do not offer the command if it's already in the comma-separated list + if [[ ",$prefix," != *",$m,"* ]]; then + COMPREPLY+=("${prefix},${m}") + fi + done + fi + return 0 + fi + + COMPREPLY=( $(compgen -W "$opts" -- "$cur") ) + return 0 + fi + + # If completing arguments for 'b conf ' + if [ "$COMP_CWORD" -eq 2 ] && [ "$prev" = "conf" ]; then + # List of directories in ~/.config/ to choose from + local config_dirs + config_dirs=$(find "$HOME/.config" -mindepth 1 -maxdepth 1 -type d -exec basename {} \; 2>/dev/null) + COMPREPLY=( $(compgen -W "$config_dirs" -- "$cur") ) + return 0 + fi +} + +# Register completion for b command +if [ -n "${BASH_VERSION:-}" ]; then + complete -F _b_completion b +fi # <<< bootstrap-cli b function <<< diff --git a/bootstrap.sh b/bootstrap.sh index aab995b..3bc3f83 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -125,6 +125,10 @@ export BOOTSTRAP_DIR="$HOME/.config/bootstrap" # <<< bootstrap-cli setup <<< EOF done + + # Initialize the last update timestamp to prevent immediate update on first execution (Fix 2) + local last_update_file="$routes_dir/.last_b_update" + date +%s 2>/dev/null > "$last_update_file" || date +%s > "$last_update_file" } # Only execute installation if not sourced (Fix 3) @@ -136,9 +140,20 @@ if [ "$is_sourced" = false ]; then . "$HOME/.config/bootstrap/b.sh" fi - # Handle sourcing the shell configuration file - if [ -n "${BASH_VERSION:-}" ] && [ -f "$HOME/.bashrc" ]; then - log_info "Sourcing ~/.bashrc..." - . "$HOME/.bashrc" + # Handle sourcing the shell configuration file or printing instructions (Fix 1) + echo + log_success "Bootstrap CLI installed successfully!" + log_info "To start using the 'b' command in this terminal session, run:" + if [ -f "$HOME/.zshrc" ]; then + echo " source ~/.zshrc" + else + echo " source ~/.bashrc" + fi +else + # Sourced mode (e.g., when sourced by installers or manually by user) + # Load the b function in the current shell context + if [ -f "$HOME/.config/bootstrap/b.sh" ]; then + . "$HOME/.config/bootstrap/b.sh" fi fi +