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
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.
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
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With