pintcat

progress - Draws progress bar & information in a shell console.

Apr 12th, 2021 (edited)
1,012
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Bash 16.48 KB | None | 0 0
  1. #####################################################################################################################
  2. # progress v3.8.0 - draws progress bar & information in a shell console according to the given value.               #
  3. # Handshake:                                                                                                        #
  4. # $PROGRESS_L1 contains character used to fill the left part of the upper bar (default: "█").                       #
  5. # $PROGRESS_R1 contains character used to fill the right part of the upper bar  (default: "_").                     #
  6. # $PROGRESS_L2 contains character used to fill the left part of the lower bar (default: "▓").                       #
  7. # $PROGRESS_R2 contains character used to fill the right part of the lower bar  (default: "▒").                     #
  8. # $PROGRESS_I contains character(s) drawn at the beginning of the bar (default: unset).                             #
  9. # $PROGRESS_O contains character(s) drawn at the end of the bar (default: unset).                                   #
  10. # $PROGRESS_P contains the percentage value. Make it empty/unset to turn it off (default: 0/on).                    #
  11. # $PROGRESS_FIX contains the fixed width of the progress bar (default: unset).                                      #
  12. # $PROGRESS_ML contains left margin of the bar (default: 0).                                                        #
  13. # $PROGRESS_MR contains right margin of the bar (default: 0).                                                       #
  14. # $PROGRESS_MAX1 contains the maximum of the value to be processed for the upper bar (default: 100).                #
  15. # $PROGRESS_MAX2 contains the maximum of the value to be processed for the lower bar (default: 100).                #
  16. # $PROGRESS_FT sets the frame type; S for single line, D for double line, F for fat frame, T for twin bars, N for   #
  17. #  a narrow framed bar. Anything else will turn off frame design and draw a simple bar instead (default).           #
  18. # $PROGRESS_TSHW sets which time information is displayed: E for elapsed time, R for remaining time, A for all      #
  19. #  these infos (default). Anything else disables the timer display.                                                 #
  20. # $PROGRESS_TPOS sets the position of the timer display: T for top (default), M for middle, B for bottom of the     #
  21. #  progress bar. Anything else disables the timer display.                                                          #
  22. # PROGRESS_TC contains the number of iterations to calculate the average total time. A higher value might be more   #
  23. #  precise, but will also take longer to calculate. (default: 10).                                                  #
  24. # Not using any of these means the corresponding default value is used.                                             #
  25. # Right margin is ignored if $PROGRESS_FIX is set.                                                                  #
  26. # PROGRESS_BAR() must be called with at least a number between 0 & $PROGRESS_MAX1 which is the progress displayed   #
  27. #  by the bar. For twin bars a 2nd value between 0 & $PROGRESS_MAX2 must be given.                                  #
  28. #####################################################################################################################
  29.  
  30. PROGRESS_L1=█
  31. PROGRESS_R1=_
  32. PROGRESS_L2="\033[38;2;130;130;130m█\033[0;0m"
  33. PROGRESS_R2="\033[38;2;65;65;65m█\033[0;0m"
  34. PROGRESS_I=
  35. PROGRESS_O=
  36. PROGRESS_P=0
  37. PROGRESS_ML=0
  38. PROGRESS_MR=0
  39. PROGRESS_MAX1=100
  40. PROGRESS_MAX2=100
  41. PROGRESS_FT=X
  42. PROGRESS_TOLD=
  43. PROGRESS_TSHW=A
  44. PROGRESS_TPOS=T
  45. PROGRESS_MPOS=M
  46. PROGRESS_TAVR=0
  47. PROGRESS_TREM=---:--:--
  48. PROGRESS_TTOT=0
  49. PROGRESS_TC=10
  50. PROGRESS_FIN=
  51. PROGRESS_STAGE=1
  52.  
  53. PROGRESS_PREP(){ # draws top, middle & bottom part of the frame & inserts timer display and/or message text if needed.
  54. # IN:  $1 contains the token for top (T), middle (M) or bottom (B) part of the frame. It will be compared to $PROGRESS_TPOS
  55. #       and $PROGRESS_MPOS to decide whether the timer display and message is included or not.
  56. #      $PROGRESS_ML contains the left margin.
  57. # OUT: Draws directly to stdout.
  58.  
  59.     PROGRESS_FRAME=$(PROGRESS_DRAW 0)
  60.     [ $1 = $PROGRESS_TPOS ] && PROGRESS_FRAME=$PROGRESS_FRAME$(printf "\033["$(($PROGRESS_ML+2))"C$PROGRESS_TOUT")
  61.     [ $1 = $PROGRESS_MPOS ] && PROGRESS_FRAME=$PROGRESS_FRAME$(printf "\033["$(($PROGRESS_ML+2))"C$PROGRESS_MSG")
  62.     printf "$PROGRESS_FRAME"
  63. }      
  64.  
  65. PROGRESS_DRAW(){ # does the actual positioning & drawing of the progress bar.
  66. # IN:  $1 must contain the actual progress given by a number between 0 and $PROGRESS_MAX.
  67. #      $PROGRESS_ML contains the left margin.
  68. #      $PROGRESS_L1 & $PROGRESS_L2 contain characters used to fill the left part of the corresponding bar.
  69. #      $PROGRESS_R1 & $PROGRESS_R2 contain characters used to fill the right part of the corresponding bar.
  70. #      $PROGRESS_I contains character(s) drawn at the beginning of the bar.
  71. #      $PROGRESS_O contains character(s) drawn at the end of the bar.
  72. #      $PROGRESS_MAX1 & $PROGRESS_MAX2 contain the maximum of the value for the corresponding bar to be processed.
  73. # OUT: Draws directly to stdout.
  74.  
  75.     PROGRESS_COUNT=0
  76.     if [ $PROGRESS_STAGE -eq 1 ]; then
  77.         PROGRESS_L=$PROGRESS_L1
  78.         PROGRESS_R=$PROGRESS_R1
  79.         PROGRESS_MAX=$PROGRESS_MAX1
  80.     else
  81.         PROGRESS_L=$PROGRESS_L2
  82.         PROGRESS_R=$PROGRESS_R2
  83.         PROGRESS_MAX=$PROGRESS_MAX2
  84.     fi
  85.     setterm -linewrap off
  86.     # If left margin was set move the start position to the right according to $PROGRESS_ML.
  87.     if [ $PROGRESS_ML -gt 0 ]; then
  88.         PROGRESS_I_TMP="\033["$PROGRESS_ML"C"$PROGRESS_I
  89.     else
  90.         PROGRESS_I_TMP="$PROGRESS_I"
  91.     fi
  92.     printf "\r$PROGRESS_I_TMP"
  93.     # Draw left part.
  94.     while [ $((PROGRESS_COUNT=$PROGRESS_COUNT+1)) -lt $(($PROGRESS_TOT*$1/$PROGRESS_MAX)) ]; do
  95.         printf %.1s && printf "$PROGRESS_L"
  96.     done
  97.     # Draw the right part.
  98.     while [ $((PROGRESS_COUNT=$PROGRESS_COUNT+1)) -le $PROGRESS_TOT ]; do
  99.         printf %.1s && printf "$PROGRESS_R"
  100.     done
  101.     # Finish drawing, print percentage & clear line.
  102.     printf "$PROGRESS_O%4s" $PROGRESS_P && printf "\033[K\r"
  103.     setterm -linewrap on
  104. }
  105.  
  106. PROGRESS_CALC(){ # measures window size; calculates & sets width of the progress bar.
  107. # IN:  $PROGRESS_FIX contains the fixed width of the progress bar. If not set, the width is calculated according to
  108. #       the window size.
  109. #      $PROGRESS_MR contains right margin of the bar.
  110. #      $PROGRESS_EXT contains the length extension for the bar; needed to calculate the actual length without $PROGRESS_I
  111. #       and $PROGRESS_O.
  112. # OUT: $PROGRESS_TOT contains the total width of the progress bar.
  113. #      $PROGRESS_P contains the percentage value displayed at the end of the progress bar.
  114.  
  115.     [ $PROGRESS_STAGE -eq 2 ] && PROGRESS_MAX=$PROGRESS_MAX2 || PROGRESS_MAX=$PROGRESS_MAX1
  116.     # Fixed width used?
  117.     if [ -n "$PROGRESS_FIX" ]; then
  118.         PROGRESS_MR=0
  119.         PROGRESS_TOT=$PROGRESS_FIX
  120.     else
  121.         # If not, calculate width in relation to window size.
  122.         PROGRESS_TOT=$(($(stty size | awk '{print $2}')-$PROGRESS_ML-$PROGRESS_MR-$PROGRESS_EXT))
  123.         if [ -n "$PROGRESS_P" ]; then
  124.             PROGRESS_TOT=$(($PROGRESS_TOT-4))
  125.             PROGRESS_P=$((100*$1/$PROGRESS_MAX))%
  126.         fi
  127.     fi
  128. }
  129.  
  130. PROGRESS_TISO(){ # changes time value into ISO pattern or interger. Given value must be either one of them.
  131. # IN:  $1 must contain the time value. If it's integer it will be converted into ISO pattern and vice versa. For the ISO
  132. #       pattern use the input format hours:minutes:seconds:milliseconds. The output format, however, will always be
  133. #       hours:minutes:seconds.
  134. # OUT: Prints the corresponding value directly to stdout.
  135.  
  136.     # If input contains anything else but numbers it's considered as ISO pattern & converted into integer.
  137.     if [ -z ${1##*[!0-9+-]*} ]; then
  138.         printf "$1" | awk -F ':' '{print ($1*1000)+$2}'
  139.     else
  140.         PROGRESS_TIN=$1
  141.         [ $PROGRESS_TIN -lt 0 ] && PROGRESS_TIN=0
  142.         PROGRESS_THRS=$(($PROGRESS_TIN/3600000))
  143.         PROGRESS_TMIN=$((($PROGRESS_TIN-$PROGRESS_THRS*3600000)/60000))
  144.         PROGRESS_TSEC=$((($PROGRESS_TIN-($PROGRESS_THRS*3600000)-($PROGRESS_TMIN*60000))/1000))
  145.         printf "%03d" $PROGRESS_THRS
  146.         printf ":%02d" $PROGRESS_TMIN
  147.         printf ":%02d" $PROGRESS_TSEC
  148.     fi
  149. }
  150.  
  151. PROGRESS_TIME(){ # counts passing time, calculates remaining time & builds timer display.
  152. # IN:  $1 must contain the actual progress given by a number between 0 and $PROGRESS_MAX.
  153. #      $PROGRESS_TSHW contains the token which sets what the timer display will show. E for elapsed time, R for remaining
  154. #       time, A for both. Anything else will deactivate the timer display.
  155. #      PROGRESS_TC contains the number of iterations to calculate the average total time. A higher value might be more
  156. #       precise, but will also take longer to calculate.
  157. # OUT: $PROGRESS_TOUT contains the ready-to-use timer display according to the $PROGRESS_TSHW setting.
  158. #      $PROGRESS_TPAS contains the elapsed time.
  159. #      $PROGRESS_TREM contains the remaining time.
  160. #      $PROGRESS_TAVR contains the estimated total time.
  161.  
  162.     PROGRESS_MAX=$PROGRESS_MAX1
  163.     [ $PROGRESS_STAGE -eq 2 ] && PROGRESS_MAX=$PROGRESS_MAX2
  164.     [ -z $PROGRESS_TC_TMP ] && PROGRESS_TC_TMP=$(($PROGRESS_TC*1000))
  165.     PROGRESS_T=$(date +%s:%3N)
  166.     [ -z $PROGRESS_TOLD ] && PROGRESS_TOLD=$PROGRESS_T
  167.     PROGRESS_TINT=$(($(PROGRESS_TISO $PROGRESS_T)-$(PROGRESS_TISO $PROGRESS_TOLD)))
  168.     PROGRESS_TPAS=$(PROGRESS_TISO $PROGRESS_TINT)
  169.     [ $1 -gt 0 ] && PROGRESS_TTOT=$((($PROGRESS_MAX*1000+$1/2)/$1*$PROGRESS_TINT))
  170.     if [ $((PROGRESS_TC=$PROGRESS_TC-1)) -ge 0 ]; then
  171.         PROGRESS_TAVR=$(($PROGRESS_TAVR+$PROGRESS_TTOT))
  172.     else
  173.         PROGRESS_TREM=$((($PROGRESS_TAVR+$PROGRESS_TC_TMP/2)/$PROGRESS_TC_TMP-$PROGRESS_TINT))
  174.         [ $PROGRESS_TREM -lt 0 ] && PROGRESS_TREM=0
  175.         PROGRESS_TREM=$(PROGRESS_TISO $PROGRESS_TREM)
  176.         PROGRESS_TAVR=0
  177.         PROGRESS_TC=$(($PROGRESS_TC_TMP/1000))
  178.     fi
  179.     case $PROGRESS_TSHW in
  180.         E)
  181.             PROGRESS_TOUT=" Time elapsed: $PROGRESS_TPAS "
  182.             ;;
  183.         R)
  184.             PROGRESS_TOUT=" Time remaining: $PROGRESS_TREM "
  185.             ;;
  186.         A)
  187.             PROGRESS_TOUT=" Time elapsed: $PROGRESS_TPAS, remaining: $PROGRESS_TREM "
  188.             ;;
  189.         *)
  190.             PROGRESS_TPOS=X
  191.             ;;
  192.     esac
  193. }
  194.  
  195. PROGRESS_BAR(){ # main part; uses all functions to build a progress bar according to the user settings; contains
  196. #                 presets for different frame types. Call this function for the most complete progress output.
  197. # IN:  $1 & $2 must contain the actual progress given by a number between 0 and $PROGRESS_MAX1 & $PROGRESS_MAX2.
  198. #       If $1 or $2 exceed the corresponding $PROGRESS_MAX they will be replaced by it.
  199. #      $PROGRESS_MAX1 & $PROGRESS_MAX2 contain the maximum of the value for the corresponding bar to be processed.
  200. #      $PROGRESS_FT contains a token to set the frame type: S for single line, D for double line, F for fat frame, T for
  201. #       twin bars, N for a narrow framed bar. Anything else will turn off frame design and draw a simple bar instead.
  202. #      $PROGRESS_ML contains the left margin.
  203. #      $PROGRESS_MR contains the right margin.
  204. #      $PROGRESS_L1 & $PROGRESS_L2 contain characters used to fill the left part of the corresponding bar.
  205. #      $PROGRESS_R1 & $PROGRESS_R2 contain characters used to fill the right part of the corresponding bar.
  206. #      $PROGRESS_I contains character(s) drawn at the beginning of the bar.
  207. #      $PROGRESS_O contains character(s) drawn at the end of the bar.
  208. #      $PROGRESS_P contains the percentage value. Make it empty/unset to turn it off.
  209. #      $PROGRESS_FIN contains an ANSI code which has to be placed at the end of a line in some cases.
  210. # OUT: $PROGRESS_NLIN contains the number of lines from the entry point to the line where the progress bar is drawn.
  211. #       This is just for orientation in case you want to place something next to the progress bar.
  212. #       Simply call PROGRESS_BAR without argument to obtain the value for the corresponding frame type.
  213. #      Anything else is drawn directly to stdout.
  214.  
  215.     case $PROGRESS_FT in
  216.         S)
  217.             PROGRESS_NLIN=2
  218.             ;;
  219.         D)
  220.             PROGRESS_NLIN=2
  221.             ;;
  222.         F)
  223.             PROGRESS_NLIN=3
  224.             ;;
  225.         T)
  226.             PROGRESS_NLIN=2
  227.             ;;
  228.         N)
  229.             PROGRESS_NLIN=2
  230.             ;;
  231.     esac
  232.     # Is input integer & between 0 & $PROGRESS_MAX1?
  233.     [ -z ${1##*[!0-9]*} ] || [ $1 -lt 0 ] && return 1
  234.     PROGRESS_EXT=$((${#PROGRESS_I}+${#PROGRESS_O}))
  235.     PROGRESS_TIME $1
  236.     case $PROGRESS_FT in
  237.         S)
  238.             PROGRESS_EXT=2
  239.             PROGRESS_P_TMP=$PROGRESS_P
  240.             PROGRESS_MR=$(($PROGRESS_MR+4))
  241.             PROGRESS_R_TMP=$PROGRESS_R1
  242.             PROGRESS_R1=─
  243.             PROGRESS_I=┌
  244.             PROGRESS_O=┐
  245.             PROGRESS_P=
  246.             PROGRESS_CALC 1
  247.             PROGRESS_PREP T    # draw top line of the frame
  248.             printf "\n\n"
  249.             PROGRESS_I=└
  250.             PROGRESS_O=┘
  251.             PROGRESS_PREP B    # draw bottom line of the frame
  252.             printf "\033[A"
  253.             PROGRESS_I=│
  254.             PROGRESS_O=│
  255.             PROGRESS_R1=$PROGRESS_R_TMP
  256.             PROGRESS_P=$PROGRESS_P_TMP
  257.             PROGRESS_MR=$(($PROGRESS_MR-4))
  258.             PROGRESS_FIN="\033[A"
  259.             ;;
  260.         D)
  261.             PROGRESS_EXT=2
  262.             PROGRESS_P_TMP=$PROGRESS_P
  263.             PROGRESS_MR=$(($PROGRESS_MR+4))
  264.             PROGRESS_R_TMP=$PROGRESS_R1
  265.             PROGRESS_R1=═
  266.             PROGRESS_I=╔
  267.             PROGRESS_O=╗
  268.             PROGRESS_P=
  269.             PROGRESS_CALC 1
  270.             PROGRESS_PREP T    # draw top line of the frame
  271.             printf "\n\n"
  272.             PROGRESS_I=╚
  273.             PROGRESS_O=╝
  274.             PROGRESS_PREP B    # draw bottom line of the frame
  275.             printf "\033[A"
  276.             PROGRESS_I=║
  277.             PROGRESS_O=║
  278.             PROGRESS_R1=$PROGRESS_R_TMP
  279.             PROGRESS_P=$PROGRESS_P_TMP
  280.             PROGRESS_MR=$(($PROGRESS_MR-4))
  281.             PROGRESS_FIN="\033[A"
  282.             ;;
  283.         F)
  284.             PROGRESS_EXT=2
  285.             PROGRESS_P_TMP=$PROGRESS_P
  286.             PROGRESS_MR=$(($PROGRESS_MR+4))
  287.             PROGRESS_R_TMP=$PROGRESS_R1
  288.             PROGRESS_TPOS=X
  289.             PROGRESS_R1=▄
  290.             PROGRESS_I=▄
  291.             PROGRESS_O=▄
  292.             PROGRESS_P=
  293.             printf "\033["$PROGRESS_ML"C$PROGRESS_TOUT\n"
  294.             PROGRESS_CALC 1
  295.             PROGRESS_PREP T    # draw top line of the frame
  296.             printf "\n\n"
  297.             PROGRESS_R1=▀
  298.             PROGRESS_I=▀
  299.             PROGRESS_O=▀
  300.             PROGRESS_PREP B    # draw bottom line of the frame
  301.             printf "\033[A"
  302.             if [ $1 -eq $PROGRESS_MAX1 ]; then
  303.                 PROGRESS_O=█
  304.             else
  305.                 PROGRESS_O=▐
  306.             fi
  307.             PROGRESS_I=█
  308.             PROGRESS_R1=$PROGRESS_R_TMP
  309.             PROGRESS_P=$PROGRESS_P_TMP
  310.             PROGRESS_MR=$(($PROGRESS_MR-4))
  311.             PROGRESS_FIN="\033[2A"
  312.             ;;
  313.         T)
  314.             [ -z ${2##*[!0-9]*} ] || [ $2 -lt 0 ] && return 1
  315.             PROGRESS_EXT=2
  316.             PROGRESS_P_TMP=$PROGRESS_P
  317.             PROGRESS_MR=$(($PROGRESS_MR+4))
  318.             PROGRESS_R_TMP=$PROGRESS_R1
  319.             PROGRESS_R1=─
  320.             PROGRESS_I=┌
  321.             PROGRESS_O=┐
  322.             PROGRESS_P=
  323.             PROGRESS_CALC 1
  324.             PROGRESS_PREP T    # draw top line of the frame
  325.             printf "\n\n"
  326.             PROGRESS_I=├
  327.             PROGRESS_O=┤
  328.             PROGRESS_PREP M    # draw middle line of the frame
  329.             printf "\n\n"
  330.             PROGRESS_I=└
  331.             PROGRESS_O=┘
  332.             PROGRESS_PREP B    # draw bottom line of the frame
  333.             printf "\033[3A"
  334.             PROGRESS_I=│
  335.             PROGRESS_O=│
  336.             PROGRESS_R1=$PROGRESS_R_TMP
  337.             PROGRESS_P=$PROGRESS_P_TMP
  338.             PROGRESS_MR=$(($PROGRESS_MR-4))
  339.             PROGRESS_FIN="\033[3A"
  340.             ;;
  341.         N)
  342.             PROGRESS_EXT=2
  343.             PROGRESS_R1="\033[7m━\033[0m"
  344.             PROGRESS_L1=█
  345.             PROGRESS_I=▐
  346.             PROGRESS_O=▌
  347.             ;;
  348.     esac
  349.     if [ $PROGRESS_FT != S ] && [ $PROGRESS_FT != D ] && [ $PROGRESS_FT != F ] && [ $PROGRESS_FT != T ]; then
  350.         case $PROGRESS_TPOS in
  351.             T)
  352.                 PROGRESS_TOUT="\033["$(($PROGRESS_ML))"C$PROGRESS_TOUT\n"
  353.                 PROGRESS_FIN="\033[A"
  354.                 ;;
  355.             B)
  356.                 PROGRESS_TOUT="\n\033["$(($PROGRESS_ML))"C$PROGRESS_TOUT\033[A"
  357.                 ;;
  358.         esac
  359.         printf "$PROGRESS_TOUT"
  360.     fi
  361.     if [ $1 -gt $PROGRESS_MAX1 ]; then
  362.         PROGRESS_CALC $PROGRESS_MAX1
  363.         PROGRESS_DRAW $PROGRESS_MAX1
  364.     else
  365.         PROGRESS_CALC $1
  366.         PROGRESS_DRAW $1
  367.     fi
  368.     if [ $PROGRESS_FT = T ] && [ -n "$2" ]; then
  369.         PROGRESS_STAGE=2
  370.         printf "\n\n"
  371.         if [ $2 -gt $PROGRESS_MAX2 ]; then
  372.             PROGRESS_CALC $PROGRESS_MAX2
  373.             PROGRESS_DRAW $PROGRESS_MAX2
  374.         else
  375.             PROGRESS_CALC $2
  376.             PROGRESS_DRAW $2
  377.         fi
  378.         PROGRESS_STAGE=1
  379.     fi
  380.     printf "$PROGRESS_FIN"
  381. }
  382.  
  383. # ANSI escape sequences to move the cursor around the screen at will...
  384.  
  385. # - Position the Cursor:
  386. #   \033[<L>;<C>H   Or  \033[<L>;<C>f
  387. #   puts the cursor at line L and column C.
  388. # - Move the cursor up N lines:
  389. #   \033[<N>A
  390. # - Move the cursor down N lines:
  391. #   \033[<N>B
  392. # - Move the cursor forward N columns:
  393. #   \033[<N>C
  394. # - Move the cursor backward N columns:
  395. #   \033[<N>D
  396.  
  397. # - Clear the screen, move to (0,0):
  398. #   \033[2J
  399. # - Erase to end of line:
  400. #   \033[K
  401.  
  402. # - Save cursor position:
  403. #   \033[s
  404. # - Restore cursor position:
  405. #   \033[u
  406.  
  407. # ASCII characters to draw lines...
  408.  
  409. # ═ ║ ╔ ╗ ╚ ╝ ╬ ╠ ╣ ╦ ╩
  410.  
  411. # ─ │ ┌ ┐ └ ┘ ┼ ├ ┤ ┬ ┴
  412.  
  413. # ╟ ╫ ╢ ╓ ╥ ╖ ╙ ╨ ╜
  414.  
  415. # ╞ ╪ ╡ ╒ ╤ ╕ ╘ ╧ ╛
  416.  
  417. # █ ▓ ▒ ░ ▄ ▀ ━ ▌ ▐ ■
  418.  
  419.  
Advertisement
Add Comment
Please, Sign In to add comment