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 :)