我遇到过*.zwc
一些文件,我认为这些文件是 Z-shell Word 代码文件或编译的zsh
脚本。
当 -ing 任意文件时source
,有没有办法zsh
:
.zwc
如果文件存在且比文件新,则使用该文件- 否则,将文件编译为 Z-shell Word Code,
source
然后
如果我有一个仅包含函数的文件,答案有什么不同吗?
关于 Z-shell Word Code 的教程似乎并不多,所以请随时向我指出。
答案1
至少为了使用.zwc
文件,您不必执行任何操作。作为.
Zsh 联机帮助页中有关命令的部分状态:
[...]如果一个文件名为'文件
.zwc
' 被发现,比文件,并且是编译形式(使用zcompile
内置创建)文件,然后从该文件中读取命令而不是文件。
对于 也是如此,因为除了搜索顺序之外,source
它与 相同。.
自动编译任何源脚本可以通过创建包装函数来完成。例如:
source () {
[[ ! "$1.zwc" -nt $1 ]] || zcompile $1
builtin source $@
}
. () {
[[ ! "$1.zwc" -nt $1 ]] || zcompile $1
builtin . $@
}
当然,因为这些包装器非常简单,可能需要一些额外的失败保存。例如,如果要获取的文件所在的目录不可写。此外,即使源文件没有语法错误,编译也可能会失败。
答案2
基于阿达丰的回答source
,我编写了和的完整替代品.
。
这并不容易,因为$@
如果没有给出参数,则传递的内置行为。
所需的别名在注释中。
compile-source-file
:
# This file needs to be `sourced` to ensure a drop-in behaviour for `source` or `.`
# The shell passess "$@" to source if no arguments are given after the file to be sourced.
# Works in bash.
# Required aliases are:
# alias source='builtin source compile-source-file source "$#" "$@"'
# alias .='builtin . compile-source-file . "$#" "$@"'
# zsh: compile functions before sourcing
# This function expects to be called with:
# $1 builtin to use, either `.` or `source`.
# $2 file to source
# $3... arguments to pass to sourced file
function compile_then_source () {
local method=$1 file=$2; shift 2; local args=("$@")
# ${var@Q} gives value of var quoted in a format that can be reused as input
[[ $BASH_VERSION ]] && { eval builtin "$method" "$file" "${args@Q}"; return $?; }
if [[ ! $file.zwc -nt $file ]]; then
# Use canonical pathname for zrecompile's happiness
if [[ -r $file && -w ${file:h} ]]; then zcompile "${file:P}"; fi
fi
eval builtin "$method" "$file" "${(q)args[@]}"
}
function main () {
local use_builtin=$1 # '.' or 'source'
local num_args=$2 # Number of elements in calling shell's $@, which follow
shift 2;
local wrapper_args=("$@")
wrapper_args=("${wrapper_args[@]:0:$num_args}")
shift "$num_args"
local file=$1; shift;
# Now $@ is the arguments passed after the file to be soured
if [[ $# -ge 1 ]]; then # arguments were passed
use_args=("$@")
else # use $@ from the wrapper args
use_args=("${wrapper_args[@]}")
fi
compile_then_source "$use_builtin" "$file" "${use_args[@]}"
}
main "$@"
unset -f main compile_then_source