53448a4a4eea90a04ddec16782daa9ecbc3eab2a
[shellsnippets/shellsnippets.git] / mksh / progress-bar
1 # -*- mode: sh -*-
2 #-
3 # Copyright © 2015, 2017
4 #       mirabilos <thorsten.glaser@teckids.org>
5 #
6 # Provided that these terms and disclaimer and all copyright notices
7 # are retained or reproduced in an accompanying document, permission
8 # is granted to deal in this work without restriction, including un‐
9 # limited rights to use, publicly perform, distribute, sell, modify,
10 # merge, give away, or sublicence.
11 #
12 # This work is provided “AS IS” and WITHOUT WARRANTY of any kind, to
13 # the utmost extent permitted by applicable law, neither express nor
14 # implied; without malicious intent or gross negligence. In no event
15 # may a licensor, author or contributor be held liable for indirect,
16 # direct, other damage, loss, or other issues arising in any way out
17 # of dealing in the work, even if advised of the possibility of such
18 # damage or existence of a defect, except proven that it results out
19 # of said person’s immediate fault when using the work as intended.
20 #-
21 # Shell library for easy display of a progress bar
22 #
23 # Usage:
24 # – before:   init_progress_bar $n
25 # – $n times: draw_progress_bar
26 # – after:    done_progress_bar
27 #
28 # init_progress_bar trashes the EXIT and SIGWINCH traps, which later
29 # are cleared, again, by done_progress_bar.
30
31 # global variables used by this library
32 _cnt_progress_bar=0
33 _cur_progress_bar=0
34 isin_progress_bar=0
35 nlin_progress_bar=0
36
37 if [[ $KSH_VERSION = @(\@\(#\)MIRBSD KSH R)@(5[5-9]|[6-9][0-9]|[1-9][0-9][0-9])\ * ]]; then
38         alias global='typeset -g'
39 else
40         alias global=global
41 fi
42
43 # args: $1 = number of draw_progress_bar calls to make up 100%
44 function init_progress_bar {
45         global -i _cnt_progress_bar=$1 _cur_progress_bar=0
46         global -i nlin_progress_bar=$LINES isin_progress_bar=1
47
48         trap 'done_progress_bar' EXIT
49         trap 'sigwinch_progress_bar' WINCH
50         # newline; up one line (to ensure we are not in the last line);
51         # save position; set scrolling region; restore position
52         print -n "\\n\\e[A\\e7\\e[1;$((# nlin_progress_bar - 1))r\\e8"
53 }
54
55 unalias global
56
57 function sigwinch_progress_bar {
58         (( isin_progress_bar )) || return 0
59
60         # get new terminal size
61         nlin_progress_bar=$LINES
62         # newline; up one line (to ensure we are not in the last line);
63         # save position; set scrolling region; restore position
64         print -n "\\n\\e[A\\e7\\e[1;$((# nlin_progress_bar - 1))r\\e8"
65 }
66
67 function done_progress_bar {
68         (( isin_progress_bar )) || return 0
69         # save position; clear scrolling region;
70         # go to last line; delete line; restore position
71         print "\\e7\\e[0;0r\\e[$nlin_progress_bar;0H\\e[M\\e8"
72         isin_progress_bar=0
73         trap - WINCH
74         trap - EXIT
75 }
76
77 function draw_progress_bar {
78         local bar num w=$COLUMNS
79
80         ((# num = (++_cur_progress_bar * w * 8) / _cnt_progress_bar ))
81         while ((# num >= 8 )); do
82                 bar+=█
83                 ((# num -= 8 ))
84         done
85         case $num {
86         (7) bar+=▉ ;;
87         (6) bar+=▊ ;;
88         (5) bar+=▋ ;;
89         (4) bar+=▌ ;;
90         (3) bar+=▍ ;;
91         (2) bar+=▎ ;;
92         (1) bar+=▏ ;;
93         }
94         # fill complete line, right-align completion percentage display
95         local -R$w spc="$((# _cur_progress_bar * 100 / _cnt_progress_bar))%"
96         # elide percentage when it stops fitting
97         ((# (_cur_progress_bar * w / _cnt_progress_bar) > (w - 4) )) && spc=
98         # save position; go to last line; set colours;
99         # output a line full of spaces (and completion percentage);
100         # jump to first column; output bar (line præfix); restore position
101         print -n -- "\\e7\\e[$nlin_progress_bar;0H\\e[0;1;33;44m$spc\\r$bar\\e8"
102 }