your daily cup of tea™

powered by

abusing ANSI escape sequences for minimal progress bars

While diving on ANSI escape sequences, it occurred to me it would be fun to do a progress bar by using only the reverse video escape codes ESC[7m and ESC[27m.

Terminal progress bars as a fun coding exercise. There are countless libraries and helpers out there written in a myriad of languages and techniques. The usual and obvious solution is by using block elements like █ and ░, and more resolution can be achieved by using eighth blocks ▏▎▍…

$ echo 'print("█" * 10 + "░" * 5)' | python
██████████░░░░░

What if instead we use the inverted foreground color to draw the bar? That way it would make it very easy to include text on the progress bar.

$ printf "\033[7mLorem ipsum dolor \033[27msit amet\n"

There are downsides though. Escape codes are just rendered, so progress bars will not carry over uninterpreted plain text. Also, resolution is limited to a single block (compared to drawing eighth blocks):

for i in {0..20}; do
  printf "\033[7m%*s\033[27m%*s▏$i\n" $i "" $((20-i)) ""
done

Here’s a minimal bash implementation. It’s a bit unreadable, but that was the fun of playing golf with it. The amount of features per number of lines is pretty great.

function barsh {
  [[ $# -lt 2 ]] && return 1
  local val=$1; local bas=$2; local txt=$3; local wid=$4;

  [[ -z $wid ]] && { [[ -z $txt ]] && wid=$bas || wid=${#txt} ; }
  [[ -z $txt ]] && txt="$(printf '%*s' "$wid" '')"
  [[ $wid -gt ${#txt} ]] && txt=$txt$(printf '%*s' $((${#txt} - wid)) '')

  local per=$(( (wid * val) / bas ))
  printf "\033[7m%s\033[27m%s" "${txt:0:$per}" "${txt:$per:$((wid-per))}"
}

Does it make sense to publish it? I do not know, but you can do the following:

$ curl https://raw.githubusercontent.com/eskerda/barsh/master/barsh.sh | bash

7 lines of bash, freely available under a MIT license :)

https://github.com/eskerda/barsh

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

This site uses Akismet to reduce spam. Learn how your comment data is processed.