8

在我的 Bash 完成文件中,我正在通过外部脚本查找完成字符串,这需要一些时间(1-2 秒)。由于这些字符串在当前 shell 运行的其余时间大部分保持不变,我想缓存它们,并且当下次触发 Bash 完成时,它应该使用缓存的字符串而不是昂贵的查找,以便它完成当它第二次运行时立即。

要通过完成文件来感受一下,这里是完成文件的重要部分:

getdeployablefiles()
{
  # How can i cache the result of 'pbt getdeployablefiles'
  # for the time the current shell runs? 
  echo `pbt getdeployablefiles`
}

have pbt &&
_pbt_complete()
{
  local cur goals

  COMPREPLY=()
  cur=${COMP_WORDS[COMP_CWORD]}
  goals=$(getdeployablefiles)
  COMPREPLY=( $(compgen -W "${goals}" -- $cur) )
  return 0
} &&
complete -F _pbt_complete pbt

如何为 shell 会话的其余部分缓存 getdeployablefiles 的输出?我在这里需要某种全局变量,或者其他一些技巧。

解决方案:

只需要制作goals非本地并询问它是否已设置。最终脚本:

getdeployablefiles()
{
  echo `pbt getdeployablefiles`
}

have pbt &&
_pbt_complete()
{
  local cur 
  if [ -z "$_pbt_complete_goals" ]; then
    _pbt_complete_goals=$(getdeployablefiles)
  fi

  _pbt_complete_goals=$(getdeployablefiles)

  COMPREPLY=()
  cur=${COMP_WORDS[COMP_CWORD]}
  COMPREPLY=( $(compgen -W "${_pbt_complete_goals}" -- $cur) )
  return 0
} &&
complete -F _pbt_complete pbt
4

3 回答 3

8

为什么不离开goals声明local并将其重命名为名称冲突可能性较低的名称 _pbt_complete_goals呢?然后您可以检查它是否为空或未设置,并在必要时设置它。

于 2011-03-16T16:14:52.257 回答
1

您可以使用当前 shell 的 PID 将缓存值写入文件,然后获取它并检查 PID 是否匹配。如果是,则使用缓存的值,否则重新计算。

于 2011-03-16T16:25:41.627 回答
1

您可以考虑的一种方法是使用bkt为您缓存数据。就像是:

_pbt_complete() {
  local cur=${COMP_WORDS[COMP_CWORD]}
  COMPREPLY=( $(compgen -W "$(bkt --ttl=10m -- pbt getdeployablefiles)" -- "$cur") )
}

应该管用。这会卸载所有缓存逻辑,只要有缓存未命中就会bkt调用这些缓存逻辑。pbt它还可以跨 shell 会话工作,因此您无需为变量范围等而苦苦挣扎。

如果您将缓存限制为给定的 shell 会话,您可以传递--scope="_pbt_complete_$$"$$扩展为当前 PID)。

如果您想在后台刷新缓存,您可以在缓存温暖但旧时传递异步--stale=1m调用。pbt显然,您可以根据需要调整--ttl--stale持续时间。

免责声明:我是作者bkt

于 2021-10-29T21:42:48.947 回答