diff --git a/install.sh b/install.sh index e53172df..af662c26 100755 --- a/install.sh +++ b/install.sh @@ -109,21 +109,77 @@ get_latest_version() { curl -s "https://api.github.com/repos/$REPO/releases/latest" | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/' } +# Resolve completion script destination for each shell +completion_path() { + local os="$1" + local shell_name="$2" + local command_name="$3" + + local data_home="${XDG_DATA_HOME:-$HOME/.local/share}" + + case "$shell_name" in + bash) + if [ "$os" = "darwin" ]; then + echo "/usr/local/etc/bash_completion.d/$command_name" + else + echo "$data_home/bash-completion/completions/$command_name" + fi + ;; + zsh) + if [ "$os" = "darwin" ]; then + echo "/usr/local/share/zsh/site-functions/_$command_name" + else + echo "$data_home/zsh/site-functions/_$command_name" + fi + ;; + fish) + echo "${XDG_CONFIG_HOME:-$HOME/.config}/fish/completions/$command_name.fish" + ;; + *) + echo "" + ;; + esac +} + +completion_dir() { + local os="$1" + local shell_name="$2" + + case "$shell_name" in + bash | zsh) + dirname "$(completion_path "$os" "$shell_name" container-use)" + ;; + fish) + echo "${XDG_CONFIG_HOME:-$HOME/.config}/fish/completions" + ;; + *) + echo "" + ;; + esac +} + # Show shell completion setup instructions show_completion_instructions() { local binary="$1" + local os="$(detect_os)" log_info "To enable shell completions:" echo "" echo " # For container-use command:" - echo " $binary completion bash > /usr/local/etc/bash_completion.d/container-use" - echo " $binary completion zsh > /usr/local/share/zsh/site-functions/_container-use" - echo " $binary completion fish > ~/.config/fish/completions/container-use.fish" + echo " mkdir -p $(completion_dir "$os" bash)" + echo " $binary completion bash > $(completion_path "$os" bash container-use)" + echo " mkdir -p $(completion_dir "$os" zsh)" + echo " $binary completion zsh > $(completion_path "$os" zsh container-use)" + echo " mkdir -p $(completion_dir "$os" fish)" + echo " $binary completion fish > $(completion_path "$os" fish container-use)" echo "" echo " # For cu command:" - echo " $binary completion --command-name=cu bash > /usr/local/etc/bash_completion.d/cu" - echo " $binary completion --command-name=cu zsh > /usr/local/share/zsh/site-functions/_cu" - echo " $binary completion --command-name=cu fish > ~/.config/fish/completions/cu.fish" + echo " mkdir -p $(completion_dir "$os" bash)" + echo " $binary completion --command-name=cu bash > $(completion_path "$os" bash cu)" + echo " mkdir -p $(completion_dir "$os" zsh)" + echo " $binary completion --command-name=cu zsh > $(completion_path "$os" zsh cu)" + echo " mkdir -p $(completion_dir "$os" fish)" + echo " $binary completion --command-name=cu fish > $(completion_path "$os" fish cu)" } # Verify checksum of downloaded file @@ -299,4 +355,6 @@ main() { fi } -main "$@" +if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then + main "$@" +fi diff --git a/scripts/test-install-completion-paths.sh b/scripts/test-install-completion-paths.sh new file mode 100755 index 00000000..fa32ffa6 --- /dev/null +++ b/scripts/test-install-completion-paths.sh @@ -0,0 +1,103 @@ +#!/usr/bin/env bash + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" + +source "$REPO_ROOT/install.sh" + +assert_equals() { + local actual="$1" + local expected="$2" + local label="$3" + + if [ "$actual" != "$expected" ]; then + echo "❌ $label" + echo " expected: $expected" + echo " actual: $actual" + exit 1 + fi +} + +assert_contains() { + local haystack="$1" + local needle="$2" + local label="$3" + + case "$haystack" in + *"$needle"*) + ;; + *) + echo "❌ $label" + echo " expected to find: $needle" + exit 1 + ;; + esac +} + +DATA_HOME="$HOME/.local/share" +CONFIG_HOME="$HOME/.config" + +assert_equals "$(completion_path linux bash container-use)" "$DATA_HOME/bash-completion/completions/container-use" "linux bash container-use" +assert_equals "$(completion_path linux zsh container-use)" "$DATA_HOME/zsh/site-functions/_container-use" "linux zsh container-use" +assert_equals "$(completion_path linux fish container-use)" "$CONFIG_HOME/fish/completions/container-use.fish" "linux fish container-use" +assert_equals "$(completion_path darwin bash container-use)" "/usr/local/etc/bash_completion.d/container-use" "darwin bash container-use" +assert_equals "$(completion_path darwin zsh container-use)" "/usr/local/share/zsh/site-functions/_container-use" "darwin zsh container-use" +assert_equals "$(completion_dir linux bash)" "$DATA_HOME/bash-completion/completions" "linux bash completion_dir" +assert_equals "$(completion_dir linux zsh)" "$DATA_HOME/zsh/site-functions" "linux zsh completion_dir" +assert_equals "$(completion_dir linux fish)" "$CONFIG_HOME/fish/completions" "linux fish completion_dir" +assert_equals "$(completion_dir darwin bash)" "/usr/local/etc/bash_completion.d" "darwin bash completion_dir" +assert_equals "$(completion_dir darwin zsh)" "/usr/local/share/zsh/site-functions" "darwin zsh completion_dir" +assert_equals "$(completion_dir darwin fish)" "$CONFIG_HOME/fish/completions" "darwin fish completion_dir" + +CUSTOM_DATA_HOME="/tmp/container-use-test-xdg-data" +CUSTOM_CONFIG_HOME="/tmp/container-use-test-xdg-config" +mkdir -p "$CUSTOM_DATA_HOME" "$CUSTOM_CONFIG_HOME" +XDG_DATA_HOME_BACKUP="${XDG_DATA_HOME:-}" +XDG_CONFIG_HOME_BACKUP="${XDG_CONFIG_HOME:-}" +export XDG_DATA_HOME="$CUSTOM_DATA_HOME" +export XDG_CONFIG_HOME="$CUSTOM_CONFIG_HOME" + +assert_equals "$(completion_path linux bash container-use)" "$CUSTOM_DATA_HOME/bash-completion/completions/container-use" "linux bash container-use with XDG_DATA_HOME" +assert_equals "$(completion_path linux zsh container-use)" "$CUSTOM_DATA_HOME/zsh/site-functions/_container-use" "linux zsh container-use with XDG_DATA_HOME" +assert_equals "$(completion_path linux fish container-use)" "$CUSTOM_CONFIG_HOME/fish/completions/container-use.fish" "linux fish container-use with XDG_CONFIG_HOME" +assert_equals "$(completion_dir linux bash)" "$CUSTOM_DATA_HOME/bash-completion/completions" "linux bash completion_dir with XDG_DATA_HOME" +assert_equals "$(completion_dir linux zsh)" "$CUSTOM_DATA_HOME/zsh/site-functions" "linux zsh completion_dir with XDG_DATA_HOME" +assert_equals "$(completion_dir linux fish)" "$CUSTOM_CONFIG_HOME/fish/completions" "linux fish completion_dir with XDG_CONFIG_HOME" + +if [ -n "$XDG_DATA_HOME_BACKUP" ]; then + export XDG_DATA_HOME="$XDG_DATA_HOME_BACKUP" +else + unset XDG_DATA_HOME +fi +if [ -n "$XDG_CONFIG_HOME_BACKUP" ]; then + export XDG_CONFIG_HOME="$XDG_CONFIG_HOME_BACKUP" +else + unset XDG_CONFIG_HOME +fi + +detect_os() { + echo "linux" +} + +linux_instructions="$(show_completion_instructions "container-use")" +assert_contains "$linux_instructions" "mkdir -p $DATA_HOME/bash-completion/completions" "linux bash mkdirp instruction" +assert_contains "$linux_instructions" "mkdir -p $DATA_HOME/zsh/site-functions" "linux zsh mkdirp instruction" +assert_contains "$linux_instructions" "mkdir -p $CONFIG_HOME/fish/completions" "linux fish mkdirp instruction" +assert_contains "$linux_instructions" "container-use completion bash > $DATA_HOME/bash-completion/completions/container-use" "linux container-use bash redirection" +assert_contains "$linux_instructions" "container-use completion --command-name=cu fish > $CONFIG_HOME/fish/completions/cu.fish" "linux cu fish redirection" +unset -f detect_os + +detect_os() { + echo "darwin" +} + +darwin_instructions="$(show_completion_instructions "container-use")" +assert_contains "$darwin_instructions" "mkdir -p /usr/local/etc/bash_completion.d" "darwin bash mkdirp instruction" +assert_contains "$darwin_instructions" "mkdir -p /usr/local/share/zsh/site-functions" "darwin zsh mkdirp instruction" +assert_contains "$darwin_instructions" "mkdir -p $HOME/.config/fish/completions" "darwin fish mkdirp instruction" +assert_contains "$darwin_instructions" "container-use completion bash > /usr/local/etc/bash_completion.d/container-use" "darwin container-use bash redirection" +unset -f detect_os + +echo "✅ install.sh completion paths behave as expected"