Progress bar

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Post Reply
Message
Author
miskox
Posts: 609
Joined: 28 Jun 2010 03:46

Progress bar

#1 Post by miskox » 15 Jul 2024 12:50

This my very old post (viewtopic.php?p=33575#p33575) should be updated with escape sequences. So here are two versions:

First solution uses escape sequences just for cursor movement, other graphics is ASCII:

Code: Select all

@echo off
cls
echo                            P R O G R E S S     B A R
call :createbinvalue  27 DEL
call :createbinvalue 218 DEL
call :createbinvalue 196 DEL
call :createbinvalue 191 DEL
call :createbinvalue 179 DEL
call :createbinvalue 192 DEL
call :createbinvalue 217 DEL
call :createbinvalue 219 DEL
echo.
echo.
echo.
echo.
echo.
echo.

set esc=%char27%
REM hide cursor
echo %esc%[?25l

set spaces=&rem
set filler=&rem
set lines=&rem
for /L %%f in (1,1,80) do call set spaces= %%spaces%%
for /L %%a in (1,1,78) do call set filler=%%char219%%%%filler%%
for /L %%f in (1,1,78) do call set lines=%%char196%%%%lines%%

set "line0=0 %%                                 50 %%                                 100 %%"
set line1=%char218%%lines%%char191%<nul
set line3=%char192%%lines%%char217%<nul

set /a cnt=0
set /a cnt_all=200

:0
set /a percent=100 * cnt / cnt_all
call :drawprogressbar %percent% "downloading %cnt%"
set /a cnt+=1

if not "%cnt%"=="201" goto :0

REM show cursor
echo %esc%[?25h

goto :EOF

:drawprogressbar
REM par1=percent
REM par2=text to echo

set line4=%~2%spaces%
set line4=%line4:~0,78%
title %cnt%
set /a proc=(78 * %1 + 22 ) / 100

call set str1=%%filler:~0,%proc%%%
set str1=%str1%%spaces%
set str1=%str1:~0,78%

set line2=%char179%%str1%%char179%<nul

echo %esc%[9F%esc%[1G
echo.
echo %line0%
echo %line1%
echo %line2%
echo %line3%
echo.
echo %line4%

goto :EOF

:createbinvalue
REM par1=decima value between 0 and 255
REM par2: if DEL set the variable only (delete chr file)
md _chrs_>nul 2>nul
if exist _chrs_\%1.chr goto :gonext
set "options=/d compress=off /d reserveperdatablocksize=26"
if %~1 neq 26  (type nul >_chrs_\t.tmp
makecab %options% /d reserveperfoldersize=%~1 _chrs_\t.tmp _chrs_\%~1.chr >nul
type _chrs_\%~1.chr | (
(for /l %%N in (1 1 38) do pause)>nul&findstr "^">_chrs_\t.tmp)
>nul copy /y _chrs_\t.tmp /a _chrs_\%~1.chr /b
del _chrs_\t.tmp
) else (copy /y nul + nul /a _chrs_\26.chr /a >nul)
:gonext
if "%2"=="DEL" (
 for /F "delims=" %%y in (_chrs_\%1.chr) do set "char%1=%%y"
del _chrs_\%1.chr
rd _chrs_
)
goto :EOF
This one does not use ASCII graphics - it uses escape sequences.

Code: Select all

@echo off
cls
echo                            P R O G R E S S     B A R
call :createbinvalue  27 DEL
call :createbinvalue 219 DEL
echo.
echo.
echo.
echo.
echo.
echo.

set esc=%char27%
REM hide cursor
echo %esc%[?25l

set spaces=&rem
set filler=&rem
set lines=&rem
for /L %%f in (1,1,80) do call set spaces= %%spaces%%
for /L %%a in (1,1,78) do call set filler=%%char219%%%%filler%%
for /L %%f in (1,1,78) do call set lines=q%%lines%%

set "line0=0 %%                                 50 %%                                 100 %%"
set line1=l%lines%k<nul
set line3=m%lines%j<nul

set /a cnt=0
set /a cnt_all=200

:0
set /a percent=100 * cnt / cnt_all
call :drawprogressbar %percent% "downloading %cnt%"
set /a cnt+=1

if not "%cnt%"=="201" goto :0

REM show cursor
echo %esc%[?25h

goto :EOF

:drawprogressbar
REM par1=percent
REM par2=text to echo

set line4=%~2%spaces%
set line4=%line4:~0,78%
title %cnt%
set /a proc=(78 * %1 + 22 ) / 100

call set str1=%%filler:~0,%proc%%%
set str1=%str1%%spaces%
set str1=%str1:~0,78%

set line2=x%str1%x<nul

echo %esc%[9F%esc%[1G
echo.
echo %esc%(0%line0%
echo %line1%
echo %line2%
echo %line3%%esc%(B
echo.
echo %line4%

goto :EOF

:createbinvalue
REM par1=decima value between 0 and 255
REM par2: if DEL set the variable only (delete chr file)
md _chrs_>nul 2>nul
if exist _chrs_\%1.chr goto :gonext
set "options=/d compress=off /d reserveperdatablocksize=26"
if %~1 neq 26  (type nul >_chrs_\t.tmp
makecab %options% /d reserveperfoldersize=%~1 _chrs_\t.tmp _chrs_\%~1.chr >nul
type _chrs_\%~1.chr | (
(for /l %%N in (1 1 38) do pause)>nul&findstr "^">_chrs_\t.tmp)
>nul copy /y _chrs_\t.tmp /a _chrs_\%~1.chr /b
del _chrs_\t.tmp
) else (copy /y nul + nul /a _chrs_\26.chr /a >nul)
:gonext
if "%2"=="DEL" (
 for /F "delims=" %%y in (_chrs_\%1.chr) do set "char%1=%%y"
del _chrs_\%1.chr
rd _chrs_
)
goto :EOF
Image

Of course color could be added...


Saso

miskox
Posts: 609
Joined: 28 Jun 2010 03:46

Re: Progress bar

#2 Post by miskox » 15 Jul 2024 23:40

Update: 3rd version: instead of character 219 this version uses DEC character 'a' (▒). See https://vt100.net/docs/vt220-rm/chapter2.html#T2-4

Code: Select all

@echo off
cls
echo                            P R O G R E S S     B A R
for /f %%a in ('echo prompt $E^| cmd') do set "ESC=%%a"
echo.
echo.
echo.
echo.
echo.
echo.

REM hide cursor
echo %esc%[?25l

set spaces=&rem
set filler=&rem
set lines=&rem
for /L %%f in (1,1,80) do call set spaces= %%spaces%%
for /L %%a in (1,1,78) do call set filler=a%%filler%%
for /L %%f in (1,1,78) do call set lines=q%%lines%%

set "line0=0 %%                                 50 %%                                 100 %%"
set line1=l%lines%k<nul
set line3=m%lines%j<nul

set /a cnt=0
set /a cnt_all=200

:0
set /a percent=100 * cnt / cnt_all
call :drawprogressbar %percent% "downloading %cnt%"
set /a cnt+=1

if not "%cnt%"=="201" goto :0

REM show cursor
echo %esc%[?25h

goto :EOF

:drawprogressbar
REM par1=percent
REM par2=text to echo

set line4=%~2%spaces%
set line4=%line4:~0,78%
title %cnt%
set /a proc=(78 * %1 + 22 ) / 100

call set str1=%%filler:~0,%proc%%%
set str1=%str1%%spaces%
set str1=%str1:~0,78%

set line2=x%str1%x<nul

echo %esc%[9F%esc%[1G
echo.
echo %esc%(0%line0%
echo %line1%
echo %line2%
echo %line3%%esc%(B
echo.
echo %line4%

goto :EOF

Also reverse/normal could be used (display a space (blank)) with %esc%[7m %esc%[27m:

Code: Select all

@echo off
cls
echo                            P R O G R E S S     B A R
for /f %%a in ('echo prompt $E^| cmd') do set "ESC=%%a"
echo.
echo.
echo.
echo.
echo.
echo.

REM hide cursor
echo %esc%[?25l

set spaces=&rem
set filler=&rem
set lines=&rem
for /L %%f in (1,1,80) do call set spaces= %%spaces%%
for /L %%a in (1,1,78) do call set filler= %%filler%%
for /L %%f in (1,1,78) do call set lines=q%%lines%%

set "line0=0 %%                                 50 %%                                 100 %%"
set line1=l%lines%k<nul
set line3=m%lines%j<nul

set /a cnt=0
set /a cnt_all=200

:0
set /a percent=100 * cnt / cnt_all
call :drawprogressbar %percent% "downloading %cnt%"
set /a cnt+=1

if not "%cnt%"=="201" goto :0

REM show cursor
echo %esc%[?25h

goto :EOF

:drawprogressbar
REM par1=percent
REM par2=text to echo

set line4=%~2%spaces%
set line4=%line4:~0,78%
title %cnt%
set /a proc=(78 * %1 + 22 ) / 100

call set str1=%%filler:~0,%proc%%%
set str1=%esc%[7m%str1%%esc%[27m%spaces%
set str1=%str1:~0,87%

set line2=x%str1%x<nul

echo %esc%[9F%esc%[1G
echo.
echo %esc%(0%line0%
echo %line1%
echo %line2%
echo %line3%%esc%(B
echo.
echo %line4%

goto :EOF

Saso

miskox
Posts: 609
Joined: 28 Jun 2010 03:46

Re: Progress bar

#3 Post by miskox » 16 Jul 2024 00:52

Of course call to the :drawprogressbar should only be called 100 times and not each time a counter increases.

Code: Select all

@echo off
cls
echo                            P R O G R E S S     B A R
for /f %%a in ('echo prompt $E^| cmd') do set "ESC=%%a"
echo.
echo.
echo.
echo.
echo.
echo.

REM hide cursor
echo %esc%[?25l

set spaces=&rem
set filler=&rem
set lines=&rem
for /L %%f in (1,1,80) do call set spaces= %%spaces%%
for /L %%a in (1,1,78) do call set filler=a%%filler%%
for /L %%f in (1,1,78) do call set lines=q%%lines%%

set "line0=0 %%                                 50 %%                                  100 %%"
set line1=l%lines%k<nul
set line3=m%lines%j<nul

set old_prc=-1
set /a cnt=0
set /a cnt_all=200

:0
set /a percent=100 * cnt / cnt_all
if not "%old_prc%"=="%percent%" (
	call :drawprogressbar %percent% "downloading %cnt%"
	set old_prc=%percent%
)
set /a cnt+=1

if not "%cnt%"=="201" goto :0

REM show cursor
echo %esc%[?25h

goto :EOF

:drawprogressbar
REM par1=percent
REM par2=text to echo

set line4=%~2%spaces%
set line4=%line4:~0,78%
title %cnt%
set /a proc=(78 * %1 + 22 ) / 100

call set str1=%%filler:~0,%proc%%%
set str1=%str1%%spaces%
set str1=%str1:~0,78%

set line2=x%str1%x<nul

echo %esc%[9F%esc%[1G
echo.
echo %esc%(0%line0%
echo %line1%
echo %line2%
echo %line3%%esc%(B
echo.
echo %line4%

goto :EOF

Saso

T3RRY
Posts: 249
Joined: 06 May 2020 10:14

Re: Progress bar

#4 Post by T3RRY » 16 Jul 2024 03:25

Nice.

Since your using escape sequences, there is another Sequence thats handy for filling space like this - ESC[nX ; where n is the number of spaces to be filled, IE the length of the prograss bar

example (the macros are just a convenient way to animate it):

Code: Select all

@Echo off & Setlocal EnableDelayedExpansion
Mode 100,40 & CLS

Call:DefMacros

for /F %%a in ('Echo(prompt $E^| cmd')Do Set \E=%%a
Set /a END=151

%While:i.start=0% (
  %@frame:Args= CSdelay 1 % (
    Set /A "i+=1" , "iD=(i*100)/End"
    Set "Info=!i!/!end! {!iD!%%} !time!"
    %$StrLen:var=Info%
    Set /a "info.pos=100 - $len.info" , "R=255-((iD*20)/10)" , "G=((iD*15)/10)"
    Echo(%\E%[H%\E%[K%\E%[48;2;!R!;!G!;m%\E%[!iD!X%\E%[0m%\E%[E%\E%[!info.pos!G%\E%[0m!info!
    %While.GEQ:i.stop=!End!%
  )
)
Pause

Endlocal & goto:Eof

:DefMacros
(Set \n=^^^

%= do not modify this \n defintion =%)


Rem .|| usage: %@Frame:Args= ElapseVAR Centisconds %
Rem .:: elapseVar    = the variable name to be used for a specific frame. allows multiple independant framerates
Rem .:: Centiseconds = an Integer corresponding to the number of centisconds between frames. Supports the use of a variable name.
for /f %%! in ("! ! ^^^!")Do ^
Set @Frame=For %%. in (1 2)Do if %%.==1 (%\n%
  For /f "tokens=1,2 Delims= " %%G in ("Args")Do If not "%%!%%G.CS%%!"=="%%!time:~-1%%!" (%\n%
    Set /A "tDiff=%%!time:~-1%%!-%%G.CS","%%G.CS=%%!time:~-1%%!"%\n%
    If "%%!tDiff:~0,-1%%!"=="-" (%\n%
      Set /A "tdiff+=10,%%G=%%G %% 100000000 + tDiff"%\n%
    )Else Set /A "%%G=%%G %% 100000000 + tDiff"%\n%
    Set /a "Target=%%H","Frame=%%!%%G%%!"%\n%
    Set "FrameNAME=%%G"%\n%
  )%\n%
)Else if %%!FRAME%%! GEQ %%!TARGET%%! Set /A "Frame=0,%%!FrameName%%!=0"^& 

REM maximum number of iterations: 16*16*16*16*16 = 1,048,576
  Set "While=For /l %%i in (1 1 16)Do If Defined Do.While"
  Set "While=Set i.start=0&Set /A "Do.While=1,i=i.start"&!While! !While! !While! !While! !While! "
  Set "End.While=Set "i.Stop=1"& Set /A "While.Condition.End=i.Stop"&If ^!i^! CONDITION ^!While.CONDITION.End^! Set "Do.While=""
  For %%G in (LSS LEQ EQU GEQ GTR NEQ)Do Set "While.%%G=!End.While:CONDITION=%%G!"
  Set "End.While=Set "Do.While=""

REM .|| $StrLen implementation by Einst as inspired by https://www.dostips.com/forum/viewtopic.php?f=3&t=1429&sid=0786ad8d7d522f4ef0ba851f1bea301d
Set "$strlenHASH=var"
for /f %%! in ("! ! ^^^!")Do ^
set $StrLen=If /i not "var"=="%%!$StrlenHASH%%!" (%\n%
    set "$=A%%!Var%%!"%\n%
    set "$3=%%!$:~7167,1%%!%%!$:~6143,1%%!%%!$:~5119,1%%!%%!$:~4095,1%%!%%!$:~3071,1%%!%%!$:~2047,1%%!%%!$:~1023,1%%!FEDCBA9876543210"%\n%
    set /A "$len.Var=0","$len.Var+=$3=0x%%!$3:~15,1%%!*1024"%\n%
    for %%# in (%%!$3%%!) do set "$=%%!$:~%%#%%!"%\n%
    if defined $ (%\n%
      set "$2=%%!$:~959,1%%!%%!$:~895,1%%!%%!$:~831,1%%!%%!$:~767,1%%!%%!$:~703,1%%!%%!$:~639,1%%!%%!$:~575,1%%!%%!$:~511,1%%!%%!$:~447,1%%!%%!$:~383,1%%!%%!$:~319,1%%!%%!$:~255,1%%!%%!$:~191,1%%!%%!$:~127,1%%!%%!$:~63,1%%!FEDCBA9876543210"%\n%
      set /A "$len.Var+=$2=0x%%!$2:~15,1%%!*64"%\n%
      for %%# in (%%!$2%%!) do set "$=%%!$:~%%#%%!"%\n%
      set "$1=%%!$%%!FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA98765432103333333333333333222222222222222211111111111111110000000000000000"%\n%
      set /A "$len.Var+=0x%%!$1:~127,1%%!%%!$1:~63,1%%!-1"%\n%
    ) else set /A "$len.Var-=1"%\n%
)
Goto:Eof

miskox
Posts: 609
Joined: 28 Jun 2010 03:46

Re: Progress bar

#5 Post by miskox » 16 Jul 2024 04:56

T3RRY wrote:
16 Jul 2024 03:25
ESC[nX
How I missed that? It has been quite a long time from the last time I used them (on DIGITAL's VT420 and VT520 video terminals on OpenVMS).

Thank you.
Saso

Post Reply