How to cache a variable used inside a Bash Completion Script for the current session
Asked Answered
W

3

9

Inside my Bash Completion file, i'm looking up completion-strings by an external script, which takes some time (1-2 seconds). Since these strings mostly stay the same for the rest of the time the current shell runs, i want to cache them and when the Bash completion is triggered the next time, it should use the cached string instead of the expensive lookup, so that it completes immediately when its run the second time.

To get a feeling about by completion file, here is the important part of the completion file:

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

How can i cache the output of getdeployablefiles for the rest of the shell session? I need some kind of global variable here, or some other trick.

Solution:

Just had to make goals non-local and ask if it's set. The final script:

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
Watermark answered 16/3, 2011 at 15:36 Comment(0)
S
1

One approach you could consider is using bkt to cache the data for you. Something like:

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

Should work. This offloads all the caching logic to bkt which invokes pbt whenever there's a cache miss. It also works across shell sessions, so you don't need to wrestle with variable scoping or the like.

If you want to limit the cache to a given shell session you can pass --scope="_pbt_complete_$$" ($$ expands to the current PID).

And if you want to refresh the cache in the background you can pass --stale=1m to invoke pbt asynchronously when the cache is warm but old. Obviously you can tune the --ttl and --stale durations as you see fit.

Disclaimer: I am the author of bkt

Starfish answered 29/10, 2021 at 21:42 Comment(0)
A
8

Why not leave goals out of the local statement and rename it to something with a low likelihood of name collision, _pbt_complete_goals perhaps? Then you could check to see if it's null or unset and set it if necessary.

Analogue answered 16/3, 2011 at 16:14 Comment(1)
I knew that there must me something wrong with my script itself. Making goals non-global and asking if it's set actually solved the problem. Thanks!Watermark
L
1

You could write the cached values to a file with the PID of the current shell, then source it and check that the PID matches. If it does, use the cached value, otherwise recalculate.

Ledezma answered 16/3, 2011 at 16:25 Comment(1)
+1 for the interesting approach. Maybe I can use that for a later problemWatermark
S
1

One approach you could consider is using bkt to cache the data for you. Something like:

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

Should work. This offloads all the caching logic to bkt which invokes pbt whenever there's a cache miss. It also works across shell sessions, so you don't need to wrestle with variable scoping or the like.

If you want to limit the cache to a given shell session you can pass --scope="_pbt_complete_$$" ($$ expands to the current PID).

And if you want to refresh the cache in the background you can pass --stale=1m to invoke pbt asynchronously when the cache is warm but old. Obviously you can tune the --ttl and --stale durations as you see fit.

Disclaimer: I am the author of bkt

Starfish answered 29/10, 2021 at 21:42 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.