我有一个不断扩大的.zshrc
文件,该文件已经失控,因此我决定尝试通过将其分解为模块化文件并获取每个文件来修复它。这在大多数情况下都有效,但我似乎有一些与变量相关的范围问题。
每个模块文件都包含一个与文件名相对应的函数。例如:nvm..zshrc
包含名为 的函数(由主.zshrc
文件调用)zshrc_config_load_nvm {}
。
下面是我正在使用的设置的简化形式。
主 .zshrc 文件
请注意,我已经彻底测试了该文件,其中的所有内容都工作正常。
# Load all config files
# This method basically copied directly from the .oh-my-zsh.sh file.
for config_file ($ZSH_CUSTOM/*.zshrc(N)); do
# Skip self-inclusion
if [[ $config_file==".zshrc" || $config_file==".zshenv" ]]; then
continue
fi
# The (D) modifier will escape the path so it can be passed to `basename`
# without quotes. the second param in `basename` removes the file extension.
local handle=$(basename ${(D)config_file} .zshrc)
# If the file contains the expected callback function name ...
# The :t filter will remove the path and file extension.
if [[ $(command -v "zshrc_config_load_${handle}") ]]; then
# ... Add it to the list of functions to call.
ZSH_CONFIG_HANDLES+=($handle)
fi
# Each config file will call the register function above.
source $config_file
done
for handle ($ZSH_CONFIG_HANDLES); do
func="zshrc_config_load_${handle}"
# Call the function
$func
done
unset config_file handle func
nvm.zshrc
# This line is copied directly from the documentation.
export NVM_DIR="$([ -z "${XDG_CONFIG_HOME-}" ] && printf %s "${HOME}/.nvm" || printf %s "${XDG_CONFIG_HOME}/nvm")"
# The callback function
function zshrc_config_load_nvm {
# Unable to access the $NVM_DIR variable in this scope.
source $NVM_DIR/nvm.sh --fast-reuse
# Error: /nvm.sh does not exist.
}
问题
如何使export
ed 全局变量可以从另一个函数的范围内访问,但不将这些值作为参数传递?
根据这个答案经过吉尔斯“所以——别再作恶了”...
export
[in] zsh 是 的简写typeset -gx
,其中属性g
表示“全局”(与函数的本地相对),属性x
表示“导出”(即在环境中)。
...因此我假设该$NVM_DIR
变量应该可以从另一个函数中使用。
答案1
您的函数将看到您之前设置的变量(无论是否导出),前提是它们尚未在子 shell 中设置或未在返回的某个函数中声明为本地变量。
您的问题来自代码中不相关的错误:
for config_file ($ZSH_CUSTOM/*.zshrc(N)); do # Skip self-inclusion if [[ $config_file==".zshrc" || $config_file==".zshenv" ]]; then continue fi
[[ somestring ]]
somestring
如果不是空字符串则返回 true 。$config_file==".zshrc"
显然不是空字符串,因此无论 的值如何, test 都会返回 true $config_file
。所以你的循环不会做任何事情。
您的意思可能是类似 的东西[[ $config_file = .zsh(rc|env) ]]
,尽管这有点毫无意义,因为它们$config_file
永远不会是.zshrc
也.zshenv
是隐藏文件,因此默认情况下不包含在全局扩展中,并且无论如何$config_file
也以 开头/path/to/zsh_custome/
(并且.zshenv
不以 结尾.zshrc
)。
if [[ $config_file -ef $0 ]] continue
检查这$config_file
不是当前正在获取的脚本可能更有意义。
其他注意事项:
export NVM_DIR="$([ -z "${XDG_CONFIG_HOME-}" ] && printf %s "${HOME}/.nvm" || printf %s "${XDG_CONFIG_HOME}/nvm")"
最好写成:
if (( $+XDG_CONFIG_HOME )); then
export NVM_DIR=$XDG_CONFIG_HOME/nvm
else
export NVM_DIR=~/.nvm
fi
在:
local handle=$(basename ${(D)config_file} .zshrc)
参数D
扩展标志(例如变成/home/you/file
)~/file
没有意义。
听起来像你想要的local handle=$config_file:t:r
(根的尾巴文件的)。
if [[ $(command -v "zshrc_config_load_${handle}") ]];
更好地写成:
if command -v "zshrc_config_load_${handle}" >& /dev/null;
这避免了分叉。或者可能if (( $+functions[zshrc_config_load_${handle}] ));
。
您可以在函数或匿名函数中使用,而不是执行var=...
... :unset var
local
function {
local var
...
}
如果有$var
来自外部作用域(或来自环境)的 a ,那么将不理会它,而不是最终取消它。