0

I have a tool that has a bash completion function installed. One specific flag value that I'm trying to complete requires making an external call to a third party program that is weirdly slow. That's fine, though. It all works. I added some local file caching so users of my tool only need to see this every few days or so.

The problem is that the slowness doesn't seem very user friendly. I don't want the user to have to know how the caching works. Yet, when the cache is dirty, they have to wait ~15 seconds for it to be rebuilt. I want to add something indicating that we're loading this data.

I've tried adding a simple echo "Querying <third party tool>...", but that interestingly seems to prevent the completion results from actually appearing until I hit tab again (presumably because it only echos that when the cache is dirty and the second time I hit tab reads straight from the cache). I've tried making it echo to stderr instead, but same result.

I'm pretty sure I've seen other tools show loading icons when tab complete is loading. Notably, gcloud shows it when completing --project. But I haven't found a sign of how they do it.

1
  • Actually, the completions not showing up was user error. Now I can get the "Loading" text to show up, but it doesn't really go away. That makes it not very usable.
    – Kat
    Jan 22, 2021 at 1:35

2 Answers 2

2

Here's a little animation:

animation() {
  tput civis
  while true; do
    for i in {1..3}; do
      echo -ne "."
      sleep 1
    done
    for i in {1..3}; do
      echo -ne "\b \b"
      sleep 1
    done
  done
  tput civvis
}

kill_animation() {
  kill $anim
  echo
}

echo -n "Loading" && animation & anim=$!

sleep 10

kill_animation

The result is this:

enter image description here

0

After some playing around, I found something that works. Basically, the idea is to backspace over the text you write, write whitespace over them, then backspace over those (the \b escape only moves the cursor and doesn't delete).

I guess that's also why the likes of gcloud displays a single character instead of text. I didn't want to animate something in Bash and didn't see a good single character that can represent loading, so what I did was:

# \e[2m = dim, \e[0m = reset
echo -ne "\e[2mLoading...\e[0m"

# do the slow thing...

# same number of `\b` and ` ` as "Loading..."
echo -ne "\b\b\b\b\b\b\b\b\b\b          \b\b\b\b\b\b\b\b\b\b"

Haven't found any issues besides that it's ugly code.

1
  • To de-ugly the code: Put each of those magic strings into a variable, with a nice name, then use the variables. Jan 22, 2021 at 7:21

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .