For those that have never seen it, the function takes a format string followed by up to 8 string arguments. The format string can contain literal text and variable place holders enclosed in square brackets. The place holders are positional, the 1st gets the 1st argument after the format, the 2nd the 2nd argument, etc. The number inside the brackets specifies the width of the output. Positive numbers are left justified, negative numbers right justified.
But the function is is relatively slow. It makes heavy use of CALL, and it is limited to a maximum of 8 string substitutions within the format string.
In response to a SS64 forum question from AiroNG, I have developed an optimized version of :Format that is ~3 times faster. I've eliminated all but one internal CALL by using delayed expansion, and I use SHIFT to eliminate the limit on the number of substitutions.
Code: Select all
@echo off
setlocal
set "format=Name: [25] Origin: [15] Age: [-3]"
call :Format "%format%" "Gerd Mueller" "Berlin" 45
call :Format "%format%" "Sally Whiteoak" "New York" 9
call :Format "%format%" "Richard Edgarson" "New Orleans" 103
exit /b
:Format Fmt [Str1] [Str2]...
setlocal disableDelayedExpansion
set "fmt=%~1"
set "line="
set "space= "
setlocal enableDelayedExpansion
for %%n in (^"^
^") do for /f "tokens=1,2 delims=[" %%a in (".!fmt:]=%%~n.!") do (
if "!!" equ "" endlocal
set "const=%%a"
call set "subst=%%~2%space%%%~2"
setlocal enableDelayedExpansion
if %%b0 geq 0 (set "subst=!subst:~0,%%b!") else set "subst=!subst:~%%b!"
for /f delims^=^ eol^= %%c in ("!line!!const:~1!!subst!") do (
endlocal
set "line=%%c"
)
shift /2
)
setlocal enableDelayedExpansion
echo(!line!
exit /b
Output:
Code: Select all
Name: Gerd Mueller Origin: Berlin Age: 45
Name: Sally Whiteoak Origin: New York Age: 9
Name: Richard Edgarson Origin: New Orleans Age: 103
I've also written a :FormatVar version that is yet 30% faster. This version passes all strings by reference. Only the name of the format variable is passed as an argument. Within each set of square brackets is the name of the variable containing the substitution string, optionally followed by a comma and the width. Again, positive is left justified, negative is right justified. If the width is missing, then the contents of the variable are inserted without any padding. This is useful to insert square bracket literals into the output.
The following code produces the exact same output as my first code. It is a good candidate to be converted to a macro

Code: Select all
@echo off
setlocal
set "format=Name: [name,25] Origin: [origin,15] Age: [age,-3]"
set "name=Gerd Mueller"
set "origin=Berlin"
set "age=45"
call :FormatVar format
set "name=Sally Whiteoak"
set "orign=New York"
set "age=103"
call :FormatVar format
set "name=Richard Edgarson"
set "origin=New Orleans"
set "age=9"
call :FormatVar format
exit /b
:FormatVar FmtVar
setlocal disableDelayedExpansion
set "line="
set "space= "
setlocal enableDelayedExpansion
for %%n in (^"^
^") do for /f "tokens=1,2 delims=[" %%a in (".!%~1:]=%%~n.!") do (
if "!!" equ "" endlocal
set "const=%%a"
set "subst="
setlocal enableDelayedExpansion
for /f "tokens=1,2 delims=," %%c in ("%%b") do (
if "%%d" equ "" (set "subst=!%%c!") else (
set "subst=!%%c!%space%!%%c!"
if %%d0 geq 0 (set "subst=!subst:~0,%%d!") else set "subst=!subst:~%%d!"
)
)
for /f delims^=^ eol^= %%c in ("!line!!const:~1!!subst!") do (
endlocal
set "line=%%c"
)
)
setlocal enableDelayedExpansion
echo(!line!
exit /b
I printed the same 3 lines 40 times (total of 120 lines) with all 3 versions and came up with the following timings:
DosTips :Format - 4.5 seconds
My :Format - 1.5 seconds
My :FormatVar - 1.0 seconds
Finally, I integrated the :color routines that have been worked on in the recent Carlos post. The color technique is inherently slow, and a real dog on XP. But it works

My :FormatColor function has similar syntax to my :FormatVar function. Except now color change specifiers may be embedded within curly braces anywhere within the format string. The color is specified using the same hex notation as is used by the COLOR command. The initial color defaults to 07 - white text on black background. I've changed the output a bit to show how variables can be used to incorporate curly brace and square bracket literals into the output.
Code: Select all
@echo off
setlocal
set "lc={"
set "rc=}"
set "ls=["
set "rs=]"
set "format=Name: {0E}[lc][name,25][rc]{07} Origin: {0C}[ls][origin,15][rs]{07} Age: {0A}[age,-3]"
set "name=Gerd Mueller"
set "origin=Berlin"
set "age=45"
call :formatColor format
set "name=Sally Whiteoak"
set "orign=New York"
set "age=9"
call :formatColor format
set "name=Richard Edgarson"
set "origin=New Orleans"
set "age=103"
call :formatColor format
exit /b
:formatColor fmt
if not defined DEL call :initColorPrint
setlocal disableDelayedExpansion
set "color=07"
set "line="
set "space= "
setlocal enableDelayedExpansion
for %%n in (^"^
^") do for /f "tokens=1,2 delims={" %%x in (".!%~1:}=%%~n.!") do (
if "!!" equ "" endlocal
set "str=%%x"
setlocal enableDelayedExpansion
for /f "tokens=1,2 delims=[" %%a in ("!str:]=%%~n.!") do (
endlocal
set "const=%%a"
set "subst="
setlocal enableDelayedExpansion
for /f "tokens=1,2 delims=," %%c in ("%%b") do (
if "%%d" equ "" (set "subst=!%%c!") else (
set "subst=!%%c!%space%!%%c!"
if %%d0 geq 0 (set "subst=!subst:~0,%%d!") else set "subst=!subst:~%%d!"
)
)
set "const=!const:~1!"
if defined const call :colorPrintVar !color! const
if defined subst call :colorPrintVar !color! subst
)
endlocal
if "%%y" neq "" set "color=%%y"
)
(echo()
exit /b
:colorPrintVar Color StrVar /n
if not defined DEL call :initColorPrint
setlocal enableDelayedExpansion
pushd .
':
cd \
set "s=!%~2!"
:: The single blank line within the following IN() clause is critical - DO NOT REMOVE
for %%n in (^"^
^") do (
set "s=!s:\=%%~n\%%~n!"
set "s=!s:/=%%~n/%%~n!"
set "s=!s::=%%~n:%%~n!"
)
set "s=!s:"=\"!"
for /f delims^=^ eol^= %%s in ("!s!") do (
if "!" equ "" setlocal disableDelayedExpansion
if %%s==\ (
findstr /a:%~1 "." "\'" nul
<nul set /p "=%DEL%%DEL%%DEL%"
) else if %%s==/ (
findstr /a:%~1 "." "/.\'" nul
<nul set /p "=%DEL%%DEL%%DEL%%DEL%%DEL%"
) else (
findstr /a:%~1 "." "%%s\..\'" nul
<nul set /p "=%DEL%%DEL%%DEL%%DEL%%DEL%%DEL%%DEL%"
)
)
if /i "%~3"=="/n" echo(
popd
exit /b
:initColorPrint
for /f %%A in ('"prompt $H&for %%B in (1) do rem"') do set "DEL=%%A %%A"
<nul >"%temp%\'" set /p "=."
subst ': "%temp%" >nul
exit /b
:cleanupColorPrint
2>nul del "%temp%\'"
>nul subst ': /d
exit /b
I can't show fixed width output with color. But the name is in yellow, the origin in blue, and the age in green

No edit was made - I momentarily lost my mind and broke the code, and have since reverted to working code

Dave Benham