如果在项目目录下有.rvmrc 文件,内容为:rvm use ruby-1.9.3-p194@gemsetname 在 cd 到项目目录时自动执行相关的 hook,请问下这个是怎么实现的?
应该是被这个脚本 Hack 了
$ cat ~/.rvm/scripts/cd
#!/usr/bin/env bash
# Source a .rvmrc file in a directory after changing to it, if it exists. To
# disable this feature, set rvm_project_rvmrc=0 in /etc/rvmrc or $HOME/.rvmrc
if (( ${rvm_project_rvmrc:-1} > 0 ))
then
__rvm_setup_cd()
{
# try to use smartcd function, fallback to builtin
typeset __cd_prefix __command
if typeset -f smartcd >/dev/null 2>/dev/null
then __cd_prefix="smartcd"
else __cd_prefix="builtin"
fi
__rvm_after_cd()
{
typeset rvm_hook
rvm_hook="after_cd"
if [[ -n "${rvm_scripts_path:-}" || -n "${rvm_path:-}" ]]
then source "${rvm_scripts_path:-$rvm_path/scripts}/hook"
fi
}
__rvm_setup_cd_function()
{
typeset __cd_prefix __command
__cd_prefix=$1
__command=$2
eval "
${__command}(){
if ${__cd_prefix} ${__command} \"\$@\"
then
[[ -n \"\${rvm_current_rvmrc:-""}\" && \"\$*\" == \".\" ]] && rvm_current_rvmrc=\"\" || true
__rvm_do_with_env_before
__rvm_project_rvmrc
__rvm_after_cd
__rvm_do_with_env_after
return 0
else
return \$?
fi
}"
}
if [[ -n "${ZSH_VERSION:-}" ]]
then
autoload is-at-least
if is-at-least 4.3.4 >/dev/null 2>&1; then
# On zsh, use chpwd_functions
export -a chpwd_functions
chpwd_functions=( "${chpwd_functions[@]}" __rvm_do_with_env_before __rvm_project_rvmrc __rvm_after_cd __rvm_do_with_env_after )
else
for __command in cd popd pushd
do __rvm_setup_cd_function "${__cd_prefix}" "${__command}"
done
fi
else
for __command in cd popd pushd
do __rvm_setup_cd_function "${__cd_prefix}" "${__command}"
done
fi
}
__rvm_setup_cd
# This functionality is opt-in by setting rvm_cd_complete_flag=1 in ~/.rvmrc
# Generic bash cd completion seems to work great for most, so this is only
# for those that have some issues with that.
if (( ${rvm_cd_complete_flag:-0} == 1 ))
then
# If $CDPATH is set, bash should tab-complete based on directories in those paths,
# but with the cd function above, the built-in tab-complete ignores $CDPATH. This
# function returns that functionality.
_rvm_cd_complete ()
{
typeset directory current matches item index sep
sep="${IFS}"
export IFS
IFS=$'\n'
COMPREPLY=()
current="${COMP_WORDS[COMP_CWORD]}"
if [[ -n "$CDPATH" && ${current:0:1} != "/" ]] ; then
index=0
# The change to IFS above means that the \tr below should replace ':'
# with a newline rather than a space. A space would be ignored, breaking
# TAB completion based on CDPATH again
for directory in $(printf "%b" "$CDPATH" | \tr -s ':' '\n') ; do
for item in $( compgen -d "$directory/$current" ) ; do
COMPREPLY[index++]=${item#$directory/}
done
done
else
COMPREPLY=( $(compgen -d ${current}) )
fi
IFS="${sep}";
}
complete -o bashdefault -o default -o filenames -o dirnames -o nospace -F _rvm_cd_complete cd
fi
fi
你可以看下 diaspora 这个开源项目,cd 进去的时候会切换到指定的 ruby@gemset ,实现也是比较简单的,你可以看下它是如何实现的。在 script/env 目录下面可以指定 ruby 和 gemset 的。