上接第三篇

代码16:通过移动光标,用批处理显示动画

17个显示彩色字符和动画的批处理代码(四)_用批处理显示动画

::: Cout cursor Macro. Author: T3RRY ::: Filename: Cout.bat
::: OS requirement: Windows 10
::: Purpose: Facilitate advanced console display output with the easy use of Virtual terminal codes
::: Uses a macro function to effect display without users needing to memorise or learn specific
::: virtual terminal sequences.
::: Enables output of text in 255 bit color at absolute or relative Y;X positions.
::: Allows cursor to be hidden or shown during and after text output. See help for more info.

@Echo off & Setlocal EnableExtensions
============================================== :# Usage
If not "%~1" == "" Echo/%~1.|findstr /LIC:"/?" > nul && (
If "%~2" == "" (Cls & Mode 1000,50 & Color 30)
If "%~2" == "Usage" ( Color 04 & ( Echo/n|choice /n /C:o 2> nul ) & timeout /T 5 > nul )
If "%~2" == "DE" ( Color 04 & Echo/ --- Delayed expansion detected^^^! Must not be enabled prior to calling %~n0 ---&( Echo/n|choice /n /C:o 2> nul ))
If not Exist "%TEMP%\%~n0helpfile.~tmp" (For /F "Delims=" %%G in ('Type "%~f0"^| Findstr.exe /BLIC:":::" 2^> nul ')Do (
For /F "Tokens=2* Delims=[]" %%v in ("%%G")Do Echo(^|%%v^|
))>"%TEMP%\%~n0helpfile.~tmp"
Type "%TEMP%\%~n0helpfile.~tmp" | More
timeout /T 60 > nul
Color 07
If "%~2" == "DE" (Exit)Else Exit /B 1
)
If "!![" == "[" Call "%~f0" "/?" "DE"
:::[=====================================================================================================================]
:::[ cout /? ]
:::[ %COUT% Cursor output macro. ]
:::[ * Valid Args for COUT: {/Y:Argvalue} {/X:Argvalue} {/S:Argvalue} {/C:Argvalue} ]
:::[ - Args Must be encased in curly braces. Arg order does not matter ; Each Arg is optional. ]
:::[ * Valid Switches for COUT: /Save /Alt /Main ]
:::[ /Save - Stores the Y and X position at the start of the current expansion to .lY and .lX variables ]
:::[ /Alt - Switch console to alternate screen Buffer. Persists until /Main switch is used. ]
:::[ /Main - Restore console to main screen Buffer. Console default is the main buffer. ]
:::[ ]
:::[ USAGE: ]
:::[ * ArgValue Options ; '#' is an integer: ]
:::[ {/Y:up|down|#} {/Y:up#|down#|#} {/Y:#up|#down|#} {/X:left|right|#} {/X:left#|right#|#} {/X:#left|#right|#} ]
:::[ * note: {/Y:option} {/X:option} - 1 option only per Arg. ]
:::[ - directions: 'up' 'down' 'left' 'right' are relative to the cursors last position. ]
:::[ - /Y and /X options - #direction or direction#: ]
:::[ Positions the cursor a number of cells from the current position in the given direction. ]
:::[ Example; To move the cursor 5 rows up in the same column, without displaying any new text: ]
:::[ %COUT%{/Y:5up} ]
:::[ - '#' (Absolute position) is the column number {/X:#} or row number {/Y:#} the cursor ]
:::[ * Integers for absolute positions contained in variables must be Expanded: {/Y:%varname%} ]
:::[ is to be positioned at, allowing cursor position to be set on single or multiple axis. ]
:::[ * Absolute Y and X positions capped at line and column maximum of the console display. ]
:::[ * Exceeding the maximum Y positions the cursor at the start of the last line in the console display. ]
:::[ * Exceeding the maximum X positions the cursor at the start of the next line ]
:::[ ]
:::[ {/S:Output String} {/S:(-)Output String} {/S:Output String(+)} {/S:Output String(K)} {/S:Output String(.#.)} ]
:::[ * note: (-) Hide or (+) Show the Cursor during output of the string. ]
:::[ (K) Clears the row of text from the position (K) occurs. ]
:::[ Example; Delete 5 characters from the current row to the right of the curser: ]
:::[ %COUT%{/S:(.5.)} ]
:::[ {/C:VTcode} {/C:VTcode-VTcode} {/C:VTcode-VTcode-VTcode} ]
:::[ * note: Chain multiple graphics rendition codes using '-' ]
:::[ See: https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences#text-formatting ]
:::[ See also: https://www.rapidtables.com/web/color/RGB_Color.html ]
:::[=====================================================================================================================]

============================================== :# PreScript variable definitions

rem /* generate Vitual Terminal Escape Control .Character */
For /F %%a in ( 'Echo prompt $E ^| cmd' )Do Set "\E=%%a"
rem /* https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences */
(Set \n=^^^

%= Newline variable for macro definitions. DO NOT MODIFY this line or above 2 lines. =%)

================== :# Screen Dimensions [Customise columns,lines using the mode command.]
Mode 160,38 & Cls
rem /* Get screen dimensions [lines] [columns]. Must be done before delayed expansion is enabled. */
For /F "tokens=1,2 Delims=:" %%G in ('Mode')Do For %%b in (%%H)Do For %%a in (%%G)Do Set "%%a=%%b"

rem /* NON ENGLISH VERSION USERS: You will need to manually set Columns and lines for their desired console size */
If not defined columns (Set "columns=100"& Set "lines=30")

rem /* Cursor position codes - https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences#simple-cursor-positioning */
Set "left=D"&Set "right=C"&Set "up=A"&set "down=B"
For /L %%n in (1 1 %lines%)Do (Set "%%ndown=[%%nB"&Set "down%%n=[%%nB"& set "%%nup=[%%nA"&Set "up%%n=[%%nA")
For /L %%n in (1 1 %columns%)Do (Set "%%nleft=[%%nD"&Set "left%%n=[%%nD"&set "%%nright=[%%nC"&set "right%%n=[%%nC")

%= Catch Args =%Set COUT=For %%n in (1 2)Do If %%n==2 ( %\n%
%= Test No Args =%If "!Args!" == "" (CLS^&Echo/Usage Error. Args Required. ^& Call "%~f0" "/?" "Usage" ^|^| Exit /B 1) %\n%
%= Test Braces Used =%If "!Args:}=!" == "!Args!" (CLS^&Echo/Usage Error. Args must be enclosed in curly braces ^& Call "%~f0" "/?" "Usage" ^|^| Exit /B 1) %\n%
%= Reset macro =%Set ".Y=" ^& Set ".X=" ^& Set ".Str=" ^& Set ".C=" %\n%
%= internal vars =%Set "Arg1=" ^& Set "Arg2=" ^& Set "Arg3=" ^& Set "Arg4=" %\n%
%= Split Args. =%For /F "Tokens=1,2,3,4 Delims={}" %%1 in ("!Args!")Do ( %\n%
%= Substring =%Set "Arg1=%%~1" %\n%
%= modification =%Set "Arg2=%%~2" %\n%
%= identifies Args =%Set "Arg3=%%~3" %\n%
%= during handling. =%Set "Arg4=%%~4" %\n%
%= =%) %\n%
%= Check /Save switch =%If not "!Args:/Save=!" == "!Args!" (%\n%
%= Reset Cursor Save =%Set ".Cpos=" ^&Set ".Char="%\n%
%= 10 char max; Repeat =%For /L %%l in (2 1 12)Do (%\n%
%= until R returned =%If not "!.Char!" == "R" (%\n%
%= from esc[6n =%^<nul set /p "=%\E%[6n" %\n%
%= Redirects to =%FOR /L %%z in (1 1 %%l) DO pause ^< CON ^> NUL%\n%
%= prevent blocking =%Set ".Char=;"%\n%
%= script execution =%for /F "tokens=1 skip=1 delims=*" %%C in ('"REPLACE /W ? . < con"') DO (Set ".Char=%%C")%\n%
%= Append string w.out R =%If "!.Cpos!" == "" (Set ".Cpos=!.Char!")Else (set ".Cpos=!.Cpos!!.Char:R=!") %\n%
%= =%)%\n%
%= =%)%\n%
%= Split Captured Pos =%For /F "tokens=1,2 Delims=;" %%X in ("!.Cpos!")Do Set ".lY=%%X" ^& Set ".LX=%%Y" %\n%
%= End of Pos /Save =%)%\n%
%= Begin Arg =%For %%i in (1 2 3 4)Do For %%S in (Y X C S)Do If not "!Arg%%i!" == "" ( %\n%
%= Processing. 4 Args =%If not "!Arg%%i:/%%S:=!" == "!Arg%%i!" ( %\n%
%= Flagged with Y X C S =%Set "Arg%%i=!Arg%%i:/%%S:=!" %\n%
%= Strip /Flag In Arg# =%For %%v in ("!Arg%%i!")Do ( %\n%
%= /Y Lines Arg handling =%If "%%S" == "Y" ( %\n%
%= Test if arg is variable =%If Not "!%%~v!" == "" ( %\n%
%= assign down / up value =%Set ".Y=%\E%!%%~v!" %\n%
%= -OR- =%)Else ( %\n%
%= assign using operation =%Set /A ".Y=!Arg%%i!" %\n%
%= to allow use of offsets; =%If !.Y! GEQ !Lines! (Set /A ".Y=Lines-1") %\n%
%= constrained to console =%Set ".Y=%\E%[!.Y!d" %\n%
%= maximum lines. =%)) %\n%
%= /X Cols Arg handling =%If "%%S" == "X" ( %\n%
%= processing follows same =%If Not "!%%~v!" == "" ( %\n%
%= logic as /Y; =%Set ".X=%\E%!%%~v!" %\n%
%= except if Columns =%)Else ( %\n%
%= exceed console max =%Set /A ".X=!Arg%%i!" %\n%
%= columns line wrapping =%If !.X! GEQ !Columns! (Set ".X=1"^& Set ".Y=%\E%!Down!") %\n%
%= is effected. =%Set ".X=%\E%[!.X!G" %\n%
%= =%)) %\n%
%= /C Color Arg Handling. %If "%%S" == "C" ( %\n%
%= Substituition =%Set ".C=%\E%[!Arg%%i!" %\n%
%= replaces '-' with VT =%Set ".C=!.C:-=m%\E%[!" %\n%
%= chain - m\E[ =%Set ".C=!.C!m" %\n%
%= =%) %\n%
%= /S String Arg Handle =%If "%%S" == "S" ( %\n%
%= Substitute Sub-Args =%Set ".Str=!Arg%%i!" %\n%
%= (-) hide cursor =%Set ".Str=!.Str:(-)=%\E%[?25l!" %\n%
%= (+) show cursor =%Set ".Str=!.Str:(+)=%\E%[?25h!" %\n%
%= (K) clear line =%Set ".Str=!.Str:(K)=%\E%[K!" %\n%
%= (.#.) delete # of =%Set ".Str=!.Str:(.=%\E%[!" %\n%
%= characters =%Set ".Str=!.Str:.)=P!" %\n%
%= =%) %\n%
%= End Arg Handling =%))) %\n%
%= /Main /Alt Switch =%If not "!Args:/Main=!" == "!Args!" ( %\n%
%= handling for =%^< nul Set /P "=%\E%[?1049l!.Y!!.X!!.C!!.Str!%\E%[0m" %\n%
%= switching console =%)Else If not "!Args:/Alt=!" == "!Args!" ( %\n%
%= buffers. No Switch =%^< nul Set /P "=%\E%[?1049h!.Y!!.X!!.C!!.Str!%\E%[0m" %\n%
%= outputs to current =%)Else ( ^< nul Set /P "=!.Y!!.X!!.C!!.Str!%\E%[0m" ) %\n%
%= buffer. =%)Else Set Args=
rem /* Simple subsecond delay macro. Uses call to a non existentent label # number of times to delay script execution. */
For /F "tokens=1,2 delims==" %%G in ('wmic cpu get maxclockspeed /format:value')Do Set /A "%%G=%%H/20" 2> nul
If not defined Maxclockspeed Set "Maxclockspeed=200"
Set "Hash=#"& Set "delay=(If "!Hash!" == "#" (Set /A "Delay.len=Maxclockspeed")Else Set "Delay.len=#")& For /L %%i in (1 1 !Delay.Len!)Do call :[_false-label_] 2> Nul"

============================================== :# Script Body [Demo]
rem /* Enable Delayed Expansion after macro definiton in order to expand macro. */
Setlocal EnableDelayedExpansion & CD "%TEMP%"
rem /* Usage examples */
%COUT%{/X:10}{/Y:5}{/C:34}{"/S:(-)hello there^^^!"}
%Delay%
rem /* Example use of mixed foreground / background color and other graphics rendition properties */
%COUT%{"/C:31-1-4-48;2;0;80;130"}{/S:Bye for now.}{/Y:down}
%Delay%
%COUT%{/Y:up}{/C:35}{/S:again}{/X:16}
%Delay%
%COUT%{"/S:(K)^_^"}{/X:right}{/C:32}{/Y:down} /Save
%Delay%
rem /* Switch to Alternate screen buffer: /Alt */
%COUT%{"/S:(-)(K)o_o"}{/X:.lX+1}{/Y:6}{/C:33}{/Y:down} /Alt
%Delay%
%COUT%{"/S:Don't worry, they'll be back"}{/Y:down}{/X:15left}{/C:7-31}
rem /* Cursor position is tied to the active console buffer. The contents of the Alternate buffer are discarded when reverting to the Main buffer. */
%Delay%
rem /* Return to Main screen buffer: /Main */
%COUT%{/X:3left}{/Y:5up}{"/S:That's all folks."} /Save /Main
rem /* Cursor position is tied to the active console buffer. */
%Delay%
rem /* restore cursor position /Save .lX value with +7 offset ; Overwrite all and delete 6 following characters:(.6.) ; restore cursor: (+) */
%COUT%{/X:10left}{/S:How(.6.)(+)}{/C:32}
rem /* The same as the above line using VT codes manually. */
::: <nul Set /P "=%\E%[10D%\E%[32mHow%\E%[6P%\E%[?25l"
%Delay%
%COUT%{/Y:100}
Endlocal
Goto :eof

代码17:更复杂的批处理代码、更炫酷的动画效果

17个显示彩色字符和动画的批处理代码(四)_用批处理显示动画_02

::: Author T3RRY : Created 09/04/2021 : Version 1.0.7
::: Version changes:
::: - ADDED /A switch to allow absolute Y;X value to be supplied as a single switch subarg
::: - ADDED /@ switch to allow saving of cursor position. Subarg allows custom return var to store multiple positions.
::: - ADDED random subarg for /C color switch.
::: - ADDED optional companion switch to /C - '/B'
::: - When /C random subarg is used, /B may be used with any ONE of the following: R G B C M Y
::: to bias the output color towards Red Green Blue Cyan Magenta or Yellow
::: - ADDED support for switches with common prefix.
::: - ADDED /T timeout switch for subsecond delays
::: - CORRECTED Switch validation method to handle Switches at EOL with no subargs
::: - ADDED /E Switch to allow /C value to be preserved or Color to be changed at EOL with an integer subarg.
::: - Support REMOVED for switch usage pattern /Switch:value
:::
::: Purpose : Color and cursor position macro for windows 10 batch files
::: - Allows rapid display of colored output at specified screen position.
::: For more information, read the usage.
:::
::: Uses macro parameter and switch handling template.
::: - See : https://pastebin.com/gzL7AYpC
::: https://stackoverflow.com/questions/2048509/how-to-echo-with-different-colors-in-the-windows-command-line

@Echo off
mode 200,60
:# Windows Version control. Assigns flag true if system is windows 10.
Set "Win10="
Ver | Findstr /LIC:" 10." > nul && Set "Win10=true"

:# Test if virtual terminal codes enabled ; enable if false
:# removes win10 flag definition if version does not support Virtual Terminal sequences
If defined Win10 (
Reg Query HKCU\Console | %SystemRoot%\System32\findstr.exe /LIC:"VirtualTerminalLevel REG_DWORD 0x1" > nul || (
Reg Add HKCU\Console /f /v VirtualTerminalLevel /t REG_DWORD /d 1
) > Nul || Set "Win10="
)
If not defined Win10 (
Echo(Virtual terminal sequences not supported on your system
Exit /B 1
)

If "%~1" == "" (
Mode 200,150
Cls
)

:# /@ Switch requires clean working driectory to execute in.
RD "%TEMP%\%~n0_Run" 2> nul && Timeout 1 > nul
MD "%TEMP%\%~n0_Run"

(Set \n=^^^

%= \n macro newline variable. Do not modify =%)

:# assign virtual terminal control character 0x27 'escape' variable \E
For /F %%a in ( 'Echo prompt $E ^| cmd' )Do Set "\E=%%a"

::# usage: %$Cout% [/?] | [/Alt | /Main] [/H [-|+]] [/T Int] [/X Int | /L Int | /R Int]
::# [/Y Int | /U Int | /D Int] [/K |/Del Int | /I Int] [/N] [/@ {Optional:ReturnVar}]
::# [/C Int | /C Int,Int | /C Int;Int | /C random] [/S "String"] [/E {Optional:0|Int}]
::# -----------------------------------------------------------------------------------------------------
::# Available Switches : Description:
::# -----------------------------------------------------------------------------------------------------
::# /? : This help screen
::#
::# /S String : String to be output. Tested for strings of 500 characters.
::# /S String{Substituion} : The following characters must be substituted for output:
::# /S ^!Variable:/={FS}^! : {AS}:* {DQ}:" {FS}:/ {EQ}:=
::#
::# /C Integer : Declare output color using VT sequence
::# /C Integer,Integer : Chain mulitple VT color sequences
::# /C Integer;Integer : Combine multiple VT values into the one sequence
::# /C random : Random RGB foreground color
::# /B R|G|B|C|M|Y : Bias /C random color toward Red Green Blue
::# : Cyan Magenta or Yellow. /C random must be used.
::# /E : Preserves /C Color value until /E 0 is used. /C must be used.
::# /E 0 : Restores color to Black BG White FG after string output.
::# /E Integer : Change color after string output to supplied value.
::#
::# /A Integer;Integer : Move cursor to Line;Column [ absolute ]
::# /Y Integer : Move cursor to Line Integer [ absolute Y ]
::# /X Integer : Move cursor to Column Integer [ absolute X ]
::# /U Integer : Move cursor Up by Integer
::# /D Integer : Move cursor Down by Integer
::# /R Integer : Move cursor Right by Integer
::# /L Integer : Move cursor Left by Integer
::#
::# /H - : Hide the cursor : Note - If Cursor state is changed during a code block
::# redirected to a file, it cannot be changed again except within a code block.
::# /H + : Show the cursor
::# /Alt : Switch to alternate buffer [ main buffer is preserved ]
::# /Main : Return to main screen buffer [ alternate buffer is cleared ]
::# /K : Clears text to right of current cursor position
::# /Del Integer : Deletes Integer columns right of the cursor, shifting existing text left
::# /I Integer : Inserts whitespace into Integer columns right of Cursor, shifting text right
::# /N : Output a newline after other switches are executed.
::# /T Integer : Subsecond Delay after output. 25000 = ~1 Second [ Depending on clockspeed ]
::#
::# /@ : Stores cursor position after execution in variables: $Cout{Y} , $Cout{X}
::# : and $Cout{pos} ( VT format 'IntY;IntX' )
::# /@ String-ReturnVar : Return values to ReturnVar{pos} ReturnVar{Y} ReturnVar{X}
::# *!* : This switch MUST NOT be used during codeblocks that redirect output
::# : Slow execution time. ~ 17x slower than typical $Cout expansion
::# : 12/100th's vs 0.7/100th's of a second [with a clockspeed of 2904]
::#
::# Notes:
::# - $Cout Macro does not support Concatenation of Expansions.
::# - No error validation is performed on switch Integer subargs. Invalid Virtual Terminal sequences
::# will be disregarded and output as a string.
::#
::# Virtual Terminal sequence resource:
::# https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences
::#
::# Virtual terminal cursor position capture code source:
::# https://stackoverflow.com/a/38240300/12343998
::# -----------------------------------------------------------------------------------------------------

Set $Cout_Switches="A" "Y" "X" "U" "D" "R" "L" "H" "Alt" "Main" "K" "Del" "I" "N" "T" "B" "C" "E" "S" "@"

Set $Cout=For %%n in (1 2)Do if %%n==2 (%\n%
For %%G in ( %$Cout_Switches% )Do Set "$Cout_Switch[%%~G]="%\n%
If not "!$Cout_args:* /=!" == "!$Cout_args!" (%\n: build $Cout.Args[!$Cout_i.Arg!] array if args present =%
Set "$Cout_leading.args=!$Cout_args:*/=!"%\n%
For /F "Delims=" %%G in ("!$Cout_leading.args!")Do Set "$Cout_leading.args=!$Cout_args:/%%G=!"%\n%
Set ^"$Cout_args=!$Cout_args:"=!"%\n%
Set "$Cout_i.arg=0"%\n%
For %%G in (!$Cout_leading.args!)Do (%\n%
Set /A "$Cout_i.arg+=1"%\n%
Set "$Cout_arg[!$Cout_i.arg!]=%%~G"%\n%
)%\n%
) Else (%\n: remove doublequotes from args before switch processing =%
Set ^"$Cout_args=!$Cout_args:"=!"%\n%
)%\n%
Set "$Cout_LastSwitch="%\n%
For /L %%L in (2 1 4)Do If "!$Cout_LastSwitch!" == "" (%\n%
If "!$Cout_Args:~-%%L,1!" == " " Set "$Cout_LastSwitch=_"%\n%
If "!$Cout_Args:~-%%L,1!" == "/" (%\n: Flag last switch true if no subargs; Works for character switches of up to 3 characters =%
For /F "Delims=" %%v in ('Set /A "%%L-1"')Do Set "$Cout_Switch[!$Cout_Args:~-%%v!]=true"%\n%
If not "!$Cout_Args:/?=!." == "!$Cout_Args!." Set "$Cout_Switch[help]=true"%\n%
Set "$Cout_Args=!$Cout_Args:~0,-%%L!"%\n%
Set "$Cout_LastSwitch=_"%\n%
)%\n%
)%\n%
For %%G in ( %$Cout_Switches% )Do If not "!$Cout_args:/%%~G =!" == "!$Cout_args!" (%\n%
Set "$Cout_Switch[%%~G]=!$Cout_Args:*/%%~G =!"%\n%
If not "!$Cout_Switch[%%~G]:*/=!" == "!$Cout_Switch[%%~G]!" (%\n%
Set "$Cout_Trail[%%~G]=!$Cout_Switch[%%~G]:*/=!"%\n%
For %%v in ("!$Cout_Trail[%%~G]!")Do (%\n%
Set "$Cout_Switch[%%~G]=!$Cout_Switch[%%~G]: /%%~v=!"%\n%
Set "$Cout_Switch[%%~G]=!$Cout_Switch[%%~G]:/%%~v=!"%\n%
)%\n%
Set "$Cout_Trail[%%~G]="%\n%
If "!$Cout_Switch[%%~G]:~-1!" == " " Set "$Cout_Switch[%%~G]=!$Cout_Switch[%%~G]:~0,-1!"%\n%
If "!$Cout_Switch[%%~G]!" == "" Set "$Cout_Switch[%%~G]=true"%\n%
)%\n%
)%\n%
If /I "!$Cout_Switch[C]!" == "random" (%\n%
If not "!$Cout_Switch[B]!" == "" (Set "$Cout_MOD=100")Else Set "$Cout_MOD=200"%\n%
Set /A "$Cout_RR=!random! %% !$Cout_MOD! + 50,$Cout_GG=!random! %% !$Cout_MOD! + 50,$Cout_BB=!random! %% !$Cout_MOD! + 50"%\n%
If /I "!$Cout_Switch[B]!" == "R" Set "$Cout_RR=250"%\n%
If /I "!$Cout_Switch[B]!" == "G" Set "$Cout_GG=250"%\n%
If /I "!$Cout_Switch[B]!" == "B" Set "$Cout_BB=250"%\n%
If /I "!$Cout_Switch[B]!" == "M" Set /A "$Cout_RR=!Random! %% 50 + 200,Cout_GG=0,$Cout_BB=!Random! %% 50 + 200"%\n%
If /I "!$Cout_Switch[B]!" == "Y" Set /A "$Cout_RR=!Random! %% 90 + 100,Cout_GG=!Random! %% 90 + 90,$Cout_BB=0"%\n%
If /I "!$Cout_Switch[B]!" == "C" Set /A "$Cout_RR=0,Cout_GG=!Random! %% 120 + 30,$Cout_BB=175"%\n%
Set "$Cout_Switch[C]=38;2;!$Cout_RR!;!$Cout_GG!;!$Cout_BB!"%\n%
)%\n%
If "!$Cout_Switch[help]!" == "true" ((For /F "Tokens=1,2 Delims=#" %%Y in ('findstr /BLIC:"::#" "%~f0"')Do @Echo(%%Z)^| @More)%\n%
If not "!$Cout_Switch[C]!" == "" (Set "$Cout_Color=%\E%[!$Cout_Switch[C]:,=m%\E%[!m")Else Set "$Cout_Color="%\n%
If not "!$Cout_Switch[Y]!" == "" (Set "$Cout_Ypos=%\E%[!$Cout_Switch[Y]!d")Else Set "$Cout_Ypos="%\n%
If not "!$Cout_Switch[X]!" == "" (Set "$Cout_Xpos=%\E%[!$Cout_Switch[X]!G")Else Set "$Cout_Xpos="%\n%
For %%d in (U D L R)Do if not "!$Cout_Switch[%%d]!" == "" (Set /A "$Cout_Switch[%%d]=!$Cout_Switch[%%d]!")%\n%
If not "!$Cout_Switch[U]!" == "" (Set "$Cout_Yoffset=%\E%[!$Cout_Switch[U]!A")Else Set "$Cout_Yoffset="%\n%
If not "!$Cout_Switch[D]!" == "" Set "$Cout_Yoffset=%\E%[!$Cout_Switch[D]!B"%\n%
If not "!$Cout_Switch[R]!" == "" (Set "$Cout_Xoffset=%\E%[!$Cout_Switch[R]!C")Else Set "$Cout_Xoffset="%\n%
If not "!$Cout_Switch[L]!" == "" Set "$Cout_Xoffset=%\E%[!$Cout_Switch[L]!D"%\n%
If "!$Cout_Switch[H]!" == "-" Set "$Cout_Cursor=%\E%[?25l"%\n%
If "!$Cout_Switch[H]!" == "+" Set "$Cout_Cursor=%\E%[?25h"%\n%
If "!$Cout_Switch[Main]!" == "true" (Set "$Cout_Buffer=%\E%[?1049l")Else Set "$Cout_Buffer="%\n%
If "!$Cout_Switch[Alt]!" == "true" Set "$Cout_Buffer=%\E%[?1049h"%\n%
If not "!$Cout_Switch[A]!" == "" (Set "$Cout_Absolutepos=%\E%[!$Cout_Switch[A]!H")Else Set "$Cout_Absolutepos="%\n%
If not "!$Cout_Switch[K]!" == "" (Set "$Cout_LineClear=%\E%[K")Else Set "$Cout_LineClear="%\n%
If not "!$Cout_Switch[Del]!" == "" (Set "$Cout_Delete=%\E%[!$Cout_Switch[Del]!P")Else Set "$Cout_Delete="%\n%
If not "!$Cout_Switch[I]!" == "" (Set "$Cout_Insert=%\E%[!$Cout_Switch[I]!@")Else Set "$Cout_Insert="%\n%
If not "!$Cout_Switch[S]!" == "" (%\n%
Set "$Cout_String=!$Cout_Switch[S]:{FS}=/!"%\n%
Set "$Cout_String=!$Cout_String:{EQ}==!"%\n%
Set "$Cout_String=!$Cout_String:{AS}=*!"%\n%
Set ^"$Cout_String=!$Cout_String:{DQ}="!"%\n%
)Else (Set "$Cout_String=")%\n%
If "!$Cout_Switch[E]!" == "true" (Set "$Cout_EOLC=!$Cout_Color!")%\n%
If not "!$Cout_Switch[E]!" == "" (Set "$Cout_EOLC=%\E%[!$Cout_Switch[E]!m")%\n%
If "!$Cout_EOLC!" == "" (Set "$Cout_EOLC=%\E%[0m")%\n%
^< nul set /P "=!$Cout_Buffer!!$Cout_Cursor!!$Cout_Absolutepos!!$Cout_Ypos!!$Cout_YOffset!!$Cout_Xpos!!$Cout_XOffset!!$Cout_Delete!!$Cout_Insert!!$Cout_Color!!$Cout_LineClear!!$Cout_String!!$COUT_EOLC!"%\n%
If "!$Cout_Switch[N]!" == "true" Echo(%\n%
If not "!$Cout_Switch[T]!" == "" (For /L %%T in (1 1 !$Cout_Switch[T]!)Do (Call )%= Delay resetting Errorlevel to 0 =%)%\n%
If "!$Cout_Switch[help]!" == "true" Pause%\n%
If not "!$Cout_Switch[@]!" == "" (%\n%
PUSHD "%TEMP%\%~n0_Run"%\n%
Set "$Cout{pos}=" ^&Set "$Cout[Char]="%\n%
For /L %%l in (2 1 8)Do (%\n%
If not "!$Cout[Char]!" == "R" (%\n%
^<nul set /p "=%\E%[6n" %\n%
FOR /L %%z in (1 1 %%l) DO pause ^< CON ^> NUL%\n%
Set "$Cout[Char]=;"%\n%
for /F "tokens=1 skip=1 delims=*" %%C in ('"REPLACE /W ? . < con"') DO (Set "$Cout[Char]=%%C")%\n%
If "!$Cout{pos}!" == "" (Set "$Cout{pos}=!$Cout[Char]!")Else (set "$Cout{pos}=!$Cout{pos}!!$Cout[Char]:R=!")%\n%
))%\n%
For /F "tokens=1,2 Delims=;" %%X in ("!$Cout{pos}!")Do Set "$Cout{Y}=%%X" ^& Set "$Cout{X}=%%Y" %\n%
If not "!$Cout_Switch[@]!" == "true" (%\n%
Set "{Pos}!$Cout_Switch[@]!=!$Cout{pos}!"%\n%
Set /A "{Y}!$Cout_Switch[@]!=$Cout{Y},{X}!$Cout_Switch[@]!=$Cout{X}"%\n%
)%\n%
POPD "%TEMP%\%~n0_Run"%\n%
)%\n%
) Else Set $Cout_args=

:# enable macro
Setlocal EnableExtensions EnableDelayedExpansion

:# facilitate testing of the macro using parameters from the command line; or Call %~n0.bat /? to see help.

if not "%~1" == "" (
%$Cout% %*
Exit /B !Errorlevel!
)

:# usage example Ascii art ; Bird with animation

:# ensures Y;X axis at screen home
%$Cout% /A 1;1

(
%$Cout% /H - /C 1,33 /S " , .-;" /N
%$Cout% /C 1,33 /S " , |\ {FS} {FS} __," /N
%$Cout% /C 1,33 /S " |\ '.`-.| |.'.-'" /N
%$Cout% /C 1,33 /S " \`'-: `; : {FS}" /N
%$Cout% /C 1,33 /S " `-._'. \'|" /N
%$Cout% /C 1,33 /S " ,_.-` ` ` ~,_" /N
%$Cout% /C 1,33 /S " '--,. "
%$Cout% /C 31 /S ".-. "
%$Cout% /C 1,33 /S ",{EQ}{DQ}{EQ}." /N
%$Cout% /C 1,33 /S " {FS} "
%$Cout% /C 31 /S "{ "
%$Cout% /C 1,36 /S "} "
%$Cout% /C 31 /S ")"
%$Cout% /C 1,33 /S "`"
%$Cout% /C 33 /S ";-."
%$Cout% /C 1,33 /S "}" /N
%$Cout% /C 1,33 /S " | "
%$Cout% /C 31 /S "'-' "
%$Cout% /C 33 /S "{FS}__ |" /N
%$Cout% /C 1,33 /S " {FS} "
%$Cout% /C 33 /S "\_,\|" /N
%$Cout% /C 1,33 /S " | (" /N
%$Cout% /C 1,33 /S " "
%$Cout% /C 31 /S "__ "
%$Cout% /C 1,33 /S "{FS} ' \" /N
%$Cout% /C random /B G /S " {FS}\_ "
%$Cout% /C 31 /S "{FS},'`"
%$Cout% /C 1,33 /S "| ' "
%$Cout% /C 31 /S ".-~^~~-." /N
%$Cout% /C random /B G /S " |`.\_ "
%$Cout% /C 31 /S "| "
%$Cout% /C 1,33 /S "{FS} ' , "
%$Cout% /C 31 /S "{FS} \" /N
%$Cout% /C random /B G /S " _{FS} `, \"
%$Cout% /C 31 /S "| "
%$Cout% /C 1,33 /S "; , . "
%$Cout% /C 31 /S "| , ' . |" /N
%$Cout% /C random /B G /S " \ `, "
%$Cout% /C 31 /S "| "
%$Cout% /C 1,33 /S "| , , "
%$Cout% /C 31 /S "| : ; : |" /N
%$Cout% /C random /B G /S " _\ `, "
%$Cout% /C 31 /S "\ "
%$Cout% /C 1,33 /S "|. , "
%$Cout% /C 31 /S "| | | | |" /N
%$Cout% /C random /B G /S " \` `. "
%$Cout% /C 31 /S "\ "
%$Cout% /C 1,33 /S "| ' "
%$Cout% /C 1,32 /S "|"
%$Cout% /C 31 /S "\_|-'|_,'\|" /N
%$Cout% /C random /B G /S " _\ `, "
%$Cout% /C 1,32 /S "`"
%$Cout% /C 1,33 /S "\ ' . ' "
%$Cout% /C 1,32 /S "| | | | | "
%$Cout% /C random /B G /S "__" /N
%$Cout% /C random /B G /S " \ `, "
%$Cout% /C 33 /S "| , ' "
%$Cout% /C 1,32 /S "|_{FS}'-|_\_{FS} "
%$Cout% /C random /B G /S "__ ,-;` {FS}" /N
%$Cout% /C random /B G /S " \ `, "
%$Cout% /C 33 /S "\ . , ' .| | | | | "
%$Cout% /C random /B G /S "_{FS}' ` _-`|" /N
%$Cout% /C random /B G /S " `\ `, "
%$Cout% /C 33 /S "\ , | | | | |"
%$Cout% /C random /B G /S "_{FS}' .{EQ}{DQ} {FS}" /N
%$Cout% /C random /B G /S " \` `, "
%$Cout% /C 33 /S "`\ \{FS}|,| ;"
%$Cout% /C random /B G /S "{FS}' .{EQ}{DQ} |" /N
%$Cout% /C random /B G /S " \ `, "
%$Cout% /C 33 /S "`\' , | ; "
%$Cout% /C random /B G /S "{FS}' {EQ}{DQ} _{FS}" /N
%$Cout% /C random /B G /S " `\ `, "
%$Cout% /C random /B M /S ".{EQ}{DQ}-. "
%$Cout% /C 1,33 /S "': "
%$Cout% /C random /B G /S "{FS}' {EQ}{DQ} .{FS}" /N
%$Cout% /C random /B G /S " jgs _`\ ;"
%$Cout% /C random /B M /S "_{ ' ; "
%$Cout% /C random /B G /S "{FS}' {EQ}{DQ} {FS}" /N
%$Cout% /C random /B G /S " _\`-{FS}__"
%$Cout% /C random /B M /S ".~ `."
%$Cout% /C 1,35,7,48;2;130;100;0 /S "8"
%$Cout% /C random /B M /S ".'.^`~-. "
%$Cout% /C random /B G /S "{EQ}{DQ} _,{FS}" /N
%$Cout% /C random /B G /S " __\ "
%$Cout% /C random /B M /S "{ '-."
%$Cout% /C 1,35,7,48;2;150;130;0 /S "|"
%$Cout% /C random /B M /S ".'.--~'`}"
%$Cout% /C random /B G /S " _{FS}" /N
%$Cout% /C random /B G /S " \ .{EQ}{DQ}` "
%$Cout% /C random /B M /S "}.-~^'"
%$Cout% /C 1,35,7,48;2;170;150;0 /S "@"
%$Cout% /C random /B M /S "'-. '-..' "
%$Cout% /C random /B G /S "__{FS}" /N
%$Cout% /C random /B G /S " _{FS} .{DQ} "
%$Cout% /C random /B M /S "{ -'.~('-._,.'"
%$Cout% /C random /B G /S "\_,{FS}" /N
%$Cout% /C random /B G /S " {FS} .{DQ} _{FS}'"
%$Cout% /C random /B M /S "`--; ; `. ;" /N
%$Cout% /C random /B G /S " .{EQ}{DQ} _{FS}' "
%$Cout% /C random /B M /S "`-..__,-'" /N
%$Cout% /C random /B G /S " __{FS}'" /N
) > "%~dp0parrot.brd"
TYPE "%~dp0parrot.brd"
DEL "%~dp0parrot.brd"

:# Just a bit of animation
For /L %%i in (0 1 25)Do (
%$Cout% /Y 25 /X 19 /C random /B M /S ".{EQ}{DQ}-. "
%$Cout% /D 1 /X 17 /C random /B M /S "_{ ' ; "
%$Cout% /D 1 /X 15 /C random /B M /S ".~ `."
%$Cout% /R 1 /C random /B M /S ".'.^`~-. "
%$Cout% /D 1 /X 14 /C random /B M /S "{ '-."
%$Cout% /R 1 /C random /B M /S ".'.--~'`}"
%$Cout% /D 1 /X 15 /C random /B M /S "}.-~^'"
%$Cout% /R 1 /C random /B M /S "'-. '-..' "
%$Cout% /D 1 /X 14 /C random /B M /S "{ -'.~('-._,.'"
%$Cout% /D 1 /X 15 /C random /B M /S "`--; ; `. ;"
%$Cout% /D 1 /X 19 /C random /B M /S "`-..__,-'"
%$Cout% /T 15 /Y 8 /X 26 /C random /B C /S }
%$Cout% /D 2 /R 5 /I 2
%$Cout% /U 1 /R 1 /C 33 /S \
%$Cout% /Y 25 /X 19 /C random /B M /S ".{EQ}{DQ}-. "
%$Cout% /D 1 /X 17 /C random /B M /S "_{ ' ; "
%$Cout% /D 1 /X 15 /C random /B M /S ".~ `."
%$Cout% /R 1 /C random /B M /S ".'.^`~-. "
%$Cout% /D 1 /X 14 /C random /B M /S "{ '-."
%$Cout% /R 1 /C random /B M /S ".'.--~'`}"
%$Cout% /D 1 /X 15 /C random /B M /S "}.-~^'"
%$Cout% /R 1 /C random /B M /S "'-. '-..' "
%$Cout% /D 1 /X 14 /C random /B M /S "{ -'.~('-._,.'"
%$Cout% /D 1 /X 15 /C random /B M /S "`--; ; `. ;"
%$Cout% /D 1 /X 19 /C random /B M /S "`-..__,-'"
%$Cout% /T 15 /Y 8 /X 26 /C random /B B /S {EQ}
%$Cout% /D 2 /R 5 /Del 2
%$Cout% /U 1 /R 1 /C 33 /S "|"
If %%i EQU 25 %$Cout% /H + /Y 34 /X 1 /N
)

Goto :Eof