#!/usr/bin/env bash # Summary: Configure the shell environment for pyenv # Usage: eval "$(pyenv init [-|--path] [--no-push-path] [--detect-shell] [--no-rehash] [])" set -e [ -n "$PYENV_DEBUG" ] && set -x # Provide pyenv completions if [ "$1" = "--complete" ]; then echo - echo --path echo --no-push-path echo --no-rehash echo --detect-shell echo bash echo fish echo ksh echo zsh exit fi mode="help" no_rehash="" no_push_path="" for args in "$@" do if [ "$args" = "-" ]; then mode="print" shift fi if [ "$args" = "--path" ]; then mode="path" shift fi if [ "$args" = "--detect-shell" ]; then mode="detect-shell" shift fi if [ "$args" = "--no-push-path" ]; then no_push_path=1 shift fi if [ "$args" = "--no-rehash" ]; then no_rehash=1 shift fi done shell="$1" if [ -z "$shell" ]; then shell="$(ps -p "$PPID" -o 'args=' 2>/dev/null || true)" shell="${shell%% *}" shell="${shell##-}" shell="${shell:-$SHELL}" shell="${shell##*/}" shell="${shell%%-*}" fi root="${0%/*}/.." function main() { case "$mode" in "help") help_ exit 1 ;; "path") print_path print_rehash exit 0 ;; "print") init_dirs print_path print_env print_completion print_rehash print_shell_function exit 0 ;; "detect-shell") detect_profile 1 print_detect_shell exit 0 ;; esac # should never get here exit 2 } function detect_profile() { local detect_for_detect_shell="$1" case "$shell" in bash ) if [ -e '~/.bash_profile' ]; then profile='~/.bash_profile' else profile='~/.profile' fi profile_explain="~/.bash_profile if it exists, otherwise ~/.profile" rc='~/.bashrc' ;; zsh ) profile='~/.zprofile' rc='~/.zshrc' ;; ksh | ksh93 | mksh ) # There are two implementations of Korn shell: AT&T (ksh93) and Mir (mksh). # Systems may have them installed under those names, or as ksh, so those # are recognized here. The obsolete ksh88 (subsumed by ksh93) and pdksh # (subsumed by mksh) are not included, since they are unlikely to still # be in use as interactive shells anywhere. profile='~/.profile' rc='~/.profile' ;; * ) if [ -n "$detect_for_detect_shell" ]; then profile= rc= else profile='your shell'\''s login startup file' rc='your shell'\''s interactive startup file' fi ;; esac } function print_detect_shell() { echo "PYENV_SHELL_DETECT=$shell" echo "PYENV_PROFILE_DETECT=$profile" echo "PYENV_RC_DETECT=$rc" } function help_() { detect_profile { case "$shell" in fish ) echo "# Add pyenv executable to PATH by running" echo "# the following interactively:" echo echo 'set -Ux PYENV_ROOT $HOME/.pyenv' echo 'set -U fish_user_paths $PYENV_ROOT/bin $fish_user_paths' echo echo "# Load pyenv automatically by appending" echo "# the following to ~/.config/fish/config.fish:" echo echo 'pyenv init - | source' echo ;; * ) echo '# Load pyenv automatically by appending' echo -n "# the following to " if [ "$profile" == "$rc" ]; then echo "$profile :" else echo echo "# ${profile_explain:-$profile} (for login shells)" echo "# and $rc (for interactive shells) :" fi echo echo 'export PYENV_ROOT="$HOME/.pyenv"' echo '[[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH"' echo 'eval "$(pyenv init -)"' ;; esac echo echo '# Restart your shell for the changes to take effect.' echo } >&2 } function init_dirs() { mkdir -p "${PYENV_ROOT}/"{shims,versions} } function print_path() { # if no_push_path is set, guard the PATH manipulation with a check on whether # the shim is already in the PATH. if [ -n "$no_push_path" ]; then case "$shell" in fish ) echo 'if not contains -- "'"${PYENV_ROOT}/shims"'" $PATH' print_path_prepend_shims echo 'end' ;; * ) echo 'if [[ ":$PATH:" != *'\':"${PYENV_ROOT}"/shims:\''* ]]; then' print_path_prepend_shims echo 'fi' ;; esac else case "$shell" in fish ) echo 'while set pyenv_index (contains -i -- "'"${PYENV_ROOT}/shims"'" $PATH)' echo 'set -eg PATH[$pyenv_index]; end; set -e pyenv_index' print_path_prepend_shims ;; * ) # Some distros (notably Debian-based) set Bash's SSH_SOURCE_BASHRC compilation option # that makes it source `bashrc` under SSH even when not interactive. # This is inhibited by a guard in Debian's stock `bashrc` but some people remove it # in order to get proper environment for noninteractive remote commands # (SSH provides /etc/ssh/sshrc and ~/.ssh/rc for that but no-one seems to use them for some reason). # This has caused an infinite `bashrc` execution loop for those people in the below nested Bash invocation (#2367). # --norc negates this behavior of such a customized Bash. echo 'PATH="$(bash --norc -ec '\''IFS=:; paths=($PATH); ' echo 'for i in ${!paths[@]}; do ' echo 'if [[ ${paths[i]} == "'\'\'"${PYENV_ROOT}/shims"\'\''" ]]; then unset '\'\\\'\''paths[i]'\'\\\'\''; ' echo 'fi; done; ' echo 'echo "${paths[*]}"'\'')"' print_path_prepend_shims ;; esac fi } function print_path_prepend_shims() { case "$shell" in fish ) echo 'set -gx PATH '\'"${PYENV_ROOT}/shims"\'' $PATH' ;; * ) echo 'export PATH="'"${PYENV_ROOT}"'/shims:${PATH}"' ;; esac } function print_env() { case "$shell" in fish ) echo "set -gx PYENV_SHELL $shell" ;; * ) echo "export PYENV_SHELL=$shell" ;; esac } function print_completion() { completion="${root}/completions/pyenv.${shell}" if [ -r "$completion" ]; then echo "source '$completion'" fi } function print_rehash() { if [ -z "$no_rehash" ]; then echo 'command pyenv rehash 2>/dev/null' fi } function print_shell_function() { commands=(`pyenv-commands --sh`) case "$shell" in fish ) cat <