自动使用“source”文件的“.zwc”版本

自动使用“source”文件的“.zwc”版本

我遇到过*.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

相关内容