Ok. I wrote a quick-and-dirty VT100 emulator in assembly language just as a proof of concept. After the output of TowerOfHanoi.b appear at the right positions (the four lines I have, at least) I was surprised of how easy is to create complex output with this method, so I couldn't resist the temptation to add color settings in the emulator and renamed it AnsiSys.exe. The result is amazing!
I prepared the following text file called Ansi2.txt with Ansi sequences, it have an ESC character (Ascii 27) before each left bracket:
Code: Select all
[2J
Foreground: 31 32 33 34 35 36 37
[1;31m Red [1;32m Green [1;33m Yellow [1;34m Blue [1;35m Magenta [1;36m Cyan [1;37m White Light: 1
Ansi colors
[1;37;41m Red [1;37;42m Green [1;37;43m Yellow [1;37;44m Blue [1;37;45m Magenta [1;37;46m Cyan [1;37;47m White [m Light: 5
Background: 41 42 43 44 45 46 47
... and the folowing Batch file called "Ansi Color Table.bat" that create a table of text color combinations using Ansi escape sequences:
EDIT 2014/11/09: I fixed a small bug in the AnsiSys.exe program that changed to black a non-given attribute, so the default colors set by COLOR command are not preserved.
Code: Select all
@echo off
setlocal EnableDelayedExpansion
if not exist AnsiSys.exe (
echo Extracting AnsiSys.exe
call :ExtractBinaryFile AnsiSys.exe
echo AnsiSys.exe file created
echo/
echo Execute: %0 ^| AnsiSys.exe
goto :EOF
)
rem Create an Ansi table of the 256 foreground/background color combinations
rem The next variable must have an Ascii ESC (27) between the equal-sign and the left braquet
set "CSI=["
echo/
echo Ansi color table of console text colors
echo/
echo ^| -^> Foreground light colors, add: ;1
echo ^|
for /L %%b in (40,1,47) do (
set "line=%CSI%%%b;30m%%b30"
for /L %%f in (31,1,37) do set "line=!line!%CSI%%%b;%%fm %%b%%f"
for /L %%f in (30,1,37) do set "line=!line!%CSI%%%b;%%f;1m %%b%%f"
echo !line!
)
echo/
for /L %%b in (40,1,47) do (
set "line=%CSI%%%b;5;30m%%b30"
for /L %%f in (31,1,37) do set "line=!line!%CSI%%%b;5;%%fm %%b%%f"
for /L %%f in (30,1,37) do set "line=!line!%CSI%%%b;5;%%f;1m %%b%%f"
echo !line!
)
echo/
echo %CSI%mLast 8 lines background light colors, add: ;5
goto :EOF
rem Extract Binary File from hexadecimal digits placed in a "resource" in this .bat file
:ExtractBinaryFile filename.ext[.cab]
setlocal EnableDelayedExpansion
set "start="
set "end="
for /F "tokens=1,3 delims=:=>" %%a in ('findstr /N /B "</*resource" "%~F0"') do (
if not defined start (
if "%%~b" equ "%~1" set start=%%a
) else if not defined end set end=%%a
)
(for /F "skip=%start% tokens=1* delims=:" %%a in ('findstr /N "^" "%~F0"') do (
if "%%a" == "%end%" goto decodeHexFile
echo %%b
)) > "%~1.hex"
:decodeHexFile
rem Modified code based on :genchr subroutine
type nul > t.tmp
(for /F "usebackq" %%a in ("%~1.hex") do (
set input=%%a
set i=0
for /L %%I in (0,2,120) do for %%i in (!i!) do if "!input:~%%i,1!" neq "" (
set hex=!input:~%%i,2!
set /A i+=2
if "!hex:~0,1!" neq "[" (
set /A chr=0x!hex!
if not exist !chr!.chr call :genchr !chr!
type !chr!.chr
) else (
for /L %%J in (1,1,5) do for %%i in (!i!) do if "!input:~%%i,1!" neq "]" (
set "hex=!hex!!input:~%%i,1!"
set /A i+=1
)
if not exist 0.chr call :genchr 0
for /L %%J in (1,1,!hex:~1!) do type 0.chr
set /A i+=1
)
)
)) > "%~1"
del *.chr
del t.tmp temp.tmp
del "%~1.hex"
rem Expand created file if extension is .cab
set "filename=%~1"
if /I "%filename:~-4%" equ ".cab" (
expand "%filename%" "%filename:~0,-4%" > NUL
del "%filename%"
)
exit /B
:genchr
REM This code creates one single byte. Parameter: int
REM Teamwork of carlos, penpen, aGerman, dbenham
REM Tested under Win2000, XP, Win7, Win8
set "options=/d compress=off /d reserveperdatablocksize=26"
if %~1 neq 26 (
makecab %options% /d reserveperfoldersize=%~1 t.tmp %~1.chr > nul
type %~1.chr | ( (for /l %%N in (1,1,38) do pause)>nul & findstr "^" > temp.tmp )
>nul copy /y temp.tmp /a %~1.chr /b
) else (
copy /y nul + nul /a 26.chr /a >nul
)
exit /B
<resource id="AnsiSys.exe">
4d5a900003[3]04[3]ffff[2]b8[7]40[35]c0[3]0e1fba0e00b409cd21b8014ccd21546869732070726f6772616d2063616e6e6f74206265207275
6e20696e20444f53206d6f64652e0d0d0a24[7]5159150315387b5015387b5015387b509b2768501b387b50e918695017387b505269636815387b50
[24]5045[2]4c010300a64dcf53[8]e0000f010b01050c0006[3]04[7]10[3]10[3]20[4]40[2]10[3]02[2]04[7]04[8]40[3]04[6]03[5]10[2]10
[4]10[2]10[6]10[11]2c20[2]3c[84]20[2]2c[27]2e74657874[3]1405[3]10[3]06[3]04[14]20[2]602e7264617461[2]5201[3]20[3]02[3]0a
[14]40[2]402e64617461[3]5001[3]30[3]02[3]0c[14]40[2]c0[464]558bec83c4e86af5e8dd04[2]a32c3040008d45ea50ff352c304000e8c304
[2]668b45f266a334304000fce87f04[2]e89e04[2]803e007429668b06662d30303c0976082c073c0f76022c1f86c43c0976082c073c0f76022c1f
d51066a3343040006a0168433140006a00ff152420400083c40c660bc00f842f01[2]803d433140001b75536a0168433140006a00ff152420400083
c40c803d433140005b75c133c048a33e3140008d3d3e314000e8ff[3]aa80fc3b74f58ac48d3d00304000b908[3]8bd9f2ae75952bd94bff149d0830
4000eb89803d433140000a743d833d30304000ff75178d45ea50ff352c304000e8e803[2]8b45eea3303040006a0168433140006a01ff151c204000
83c40cff0536304000e943ffffff833d363040[2]744066833d343040000774368d3d3a30400066a1343040008b0d36304000f366ab6844314000ff
3530304000ff3536304000683a304000ff352c304000e88c03[2]33c0a33630400048a330304000c605433140000d6a0168433140006a01ff151c20
400083c40cc605433140000a6a0168433140006a01ff151c20400083c40ce9b6feffff6a00e82903[2]32ff6a0168433140006a00ff152420400083
c40ca0433140003c30726d3c3977692c308af86a0168433140006a00ff152420400083c40ca0433140003c30724a3c3977462c308ae7d50a8af86a01
68433140006a00ff152420400083c40ca0433140003c3072233c39771f2c308ae7d50a8af86a0168433140006a00ff152420400083c40ca043314000
8ae786c4c3803d3e31400002751b6828304000ff152020400083c40433c0a33630400048a330304000c3e8eb01[2]a03e314000fec80fb6d8c1e310
a03f314000fec8660fb6d853ff352c304000e85e02[2]c3e8c101[2]668b1d343040008d353e314000ac3cff747b3c007504b307ebf33c01750580cb
08ebea3c05750580cb80ebe13c1e72dd3c2577272c1e3c017504b004eb163c037504b006eb0e3c047504b001eb063c067502b00380e3f80ad8ebb23c
2872ae3c2f77aa2c283c017504b004eb163c037504b006eb0e3c047504b001eb063c067502b00380e38fc0e0040ad8eb8066891d34304000c3558bec
83c4e8e82101[2]8d45ea50ff352c304000e89d01[2]668b45f0660fbe1d3e3140006683fbff750366f7db662bc37c13668945f08b5dee53ff352c30
4000e87c01[2]c9c3558bec83c4e8e8d8[3]8d45ea50ff352c304000e85401[2]668b45f0660fbe1d3e3140006683fbff750366f7db6603c3663b45
ec7f13668945f08b5dee53ff352c304000e82f01[2]c9c3558bec83c4e8e88b[3]8d45ea50ff352c304000e80701[2]668b45ee660fbe1d3e314000
6683fbff750366f7db662bc37c13668945ee8b5dee53ff352c304000e8e6[3]c9c3558bec83c4e8e842[3]8d45ea50ff352c304000e8be[3]668b45
ee660fbe1d3e3140006683fbff750366f7db6603c3663b45ea7f13668945ee8b5dee53ff352c304000e899[3]c9c3833d363040[2]744066833d3430
40000774368d3d3a30400066a1343040008b0d36304000f366ab6844314000ff3530304000ff3536304000683a304000ff352c304000e854[3]33c0
a33630400048a330304000c3e847[3]8bf08a06463c2275098a06463c2275f9eb0c8a06463c20740484c075f54ec38a06463c2074f94ec3ccff2500
204000ff2504204000ff2508204000ff250c204000ff2510204000ff2514204000ff2524204000ff251c204000ff25202040[237]9420[2]a220[2]
c020[2]d020[2]ec20[2]0a21[6]3221[2]3c21[2]2a21[6]6820[10]1c21[3]20[2]8420[10]4621[2]1c20[22]9420[2]a220[2]c020[2]d020[2]
ec20[2]0a21[6]3221[2]3c21[2]2a21[6]9b004578697450726f6365737300f500476574436f6e736f6c6553637265656e427566666572496e666f
[2]6a0147657453746448616e646c65[2]6d02536574436f6e736f6c65437572736f72506f736974696f6e[2]f2025772697465436f6e736f6c654f
757470757441747472696275746500e600476574436f6d6d616e644c696e6541006b65726e656c33322e646c6c[2]73015f7265616400f8015f7772
697465[2]b00273797374656d[2]6d73766372742e646c6c[176]48664a6d41424344691240006912400044124000931240002d134000761340000c
144000c3134000434c53[5]ffffffff07[269]ff[189]
</resource>
Note that previous file also create the AnsiSys.exe program. Below is the result of execute this line:
Code: Select all
( type Ansi2.txt & "Ansi Color Table.bat" ) | AnsiSys.exe
The use of Ansi sequences is particularly useful for Batch files, because it is very easy to add colors at different screen positions. For example, the next file is called AnsiDir.bat:
Code: Select all
@echo off
setlocal EnableDelayedExpansion
rem AnsiDir.bat: show DIR output in different colors
rem Antonio Perez Ayala
rem Define the Ansi colors used in the parameters
set "CSI=["
set "Gray=%CSI%40;5;37;1m"
set color=40
for %%a in (Red Green Yellow Blue Magenta Cyan White) do (
set /A color+=1
set "%%a=%CSI%!color!;5;37;1m"
)
set "dirArgs="
:nextArg
set "arg=%~1"
if "%arg:~0,1%" equ "." goto nextColor
set "dirArgs=%dirArgs% %arg%"
shift
if "%~1" neq "" goto nextArg
goto continue
:nextColor
set "color[%~1]=!%~2!"
shift & shift
if "%~1" neq "" goto nextColor
:continue
(for /F "tokens=1* delims=:" %%a in ('dir %dirArgs% ^| findstr /N "^"') do (
set "line=%%b"
set "ext=!line:~-4!"
if not defined color[!ext!] (
echo/!line!
) else (
for %%e in (!ext!) do echo !color[%%e]!!line!%CSI%m
)
)) > AnsiDir.txt
AnsiSys.exe < AnsiDir.txt
del AnsiDir.txt
Previous Batch file take in the first parameters the ones that will be passed to a DIR command, and in the last parameters a list of ".ext=color" pairs; the possible colors are: Gray, Red, Green, Yellow, Blue, Magenta, Cyan and White. For example, below is a comparison of "dir Ansi*.*" command vs. "AnsiDir Ansi*.* .asm=Red .exe=Blue .txt=Gray" when executed in my computer:
I then added an initial color attribute to AnsiSys.exe program that may be useful to display any text, with no Ansi escape sequences, in a given color. For example, to view if a file have spaces after the last visible character in each line, just use: "AnsiSys.exe 1F < anyFile.txt", or to implement the frequently-requested feature of differentiate lines sent to Stderr from normal Stdout lines, use "anyCommand 2>&1 1>&3 | AnsiSys.exe attrib". As exampe of this feature, we use this "Ansi Error.bat" file that send a couple lines to Stderr:
Code: Select all
@echo off
echo This line to Stdout
ping -n 2 -w 1 localhost > NUL
echo THIS LINE IS AN ERROR! >&2
ping -n 2 -w 1 localhost > NUL
echo This line is normal
ping -n 2 -w 1 localhost > NUL
echo Another line to Stderr >&2
ping -n 2 -w 1 localhost > NUL
echo The last normal line
... and run it this way:
Code: Select all
"Ansi Error.bat" 2>&1 1>&3 | AnsiSys.exe 4E
IMPORTANT: The version of AnsiSys.exe program included here have not any error checking, so the program output will be wrong if the screen scrolls without a new Ansi escape sequence or end of line, and the program will crash if there are more than 128 characters without a new Ansi escape sequence or end of line.
Enjoy!
Antonio
PS - I have not steam enough to check if the ESCape character (Ascii 27) used in CSI variable may be correctly copied when it is copy-pasted from this site.
If not, I'll appreciate it if someone post the right method to generate the ESC.