IF THEN syntactic sugar
Posted: 16 Feb 2013 17:34
A quick preface: I enjoy batch's ubiquity, and so while I mostly work with 32-bit x86 assembly, C++ and the occasional interpreted language, I do a fair bit of goofy small projects with batch. Something that always bugged me was how strict batch's IF statement parenthesis were. Namely, I prefer the following format:
but obviously this format doesn't work in batch. Less obviously, the following doesn't work either:
Line continuations work almost everywhere in batch, but for whatever reason the parser is much more picky with IF statements. Of note, )^ (before the else) does work.
Batch also lacks an OR statement to be used in IF statements (IF itself can substitute for AND).
And so, I present what I've been playing with for the past few days, some syntactic sugar to make batch IF statements more palatable, at least for myself.
I'll start with the structural var:
How it works is simple:
within (:)^
The downside is that you have to affix %^% onto the end of each IF and ELSE line where you want the next line to contain a dummy ( symbol, and for the ) before else you need to make it )^, but for me personally, I find it worthwhile.
Now, for something that might have broader appeal, I present the OR statement:
I use "call;" to set errorlevel to 0 and "call" (no space after the command) to set errorlevel to 1.
There are some obvious caveats:
I haven't yet exhaustively tested this, but it's held up in every instance where I've used it so far and is more or less what I'd like to have a dialogue about.
Some bonus tidbits:
And finally, a big fat block of batch I put at the start of my most recent batch file to make sure things will work as I expect:
Queue
Code: Select all
if a > b
(
echo Y
)
else
(
echo N
)
but obviously this format doesn't work in batch. Less obviously, the following doesn't work either:
Code: Select all
if %a% gtr %b% ^
(
echo Y
)^
else ^
(
echo N
)
Line continuations work almost everywhere in batch, but for whatever reason the parser is much more picky with IF statements. Of note, )^ (before the else) does work.
Batch also lacks an OR statement to be used in IF statements (IF itself can substitute for AND).
And so, I present what I've been playing with for the past few days, some syntactic sugar to make batch IF statements more palatable, at least for myself.
I'll start with the structural var:
Code: Select all
set "^=(:)^
if a==a %^%
(
echo Y
)^
else %^%
(
echo N
)
How it works is simple:
within (:)^
- the ( gives the IF statement the opening parenthesis it wants
- the : fools the parser into ignoring the line and immediately advancing one line (in this case to the echo command)
- the ) serves no real purpose other than taking up space; it could actually be nearly any character
- the ^ is a line continuation so that the next line (the lone ( symbol) is ignored
The downside is that you have to affix %^% onto the end of each IF and ELSE line where you want the next line to contain a dummy ( symbol, and for the ) before else you need to make it )^, but for me personally, I find it worthwhile.
Now, for something that might have broader appeal, I present the OR statement:
Code: Select all
set "^=(:)^
set "if=call;&(if
set "or=call)&&(if
set "and=if
set "then=call)&if;errorlevel;1
%if% a==a %and% a==b %or% %errorlevel%==0 %or% not a==a %then% %^%
(
echo Y
)^
else %^%
(
echo N
)
I use "call;" to set errorlevel to 0 and "call" (no space after the command) to set errorlevel to 1.
There are some obvious caveats:
- the current errorlevel will be lost without adding code to restore it within both the IF and ELSE blocks
- a specialized %if% is required to start the statement rather than just IF
- a specialized %then% is required to finish the statement rather than nothing
- if you want to test the errorlevel within the IF statement, you have to use a %errorlevel% comparison instead of the special errorlevel statement
I haven't yet exhaustively tested this, but it's held up in every instance where I've used it so far and is more or less what I'd like to have a dialogue about.
Some bonus tidbits:
Code: Select all
set "&&=||:&if;not;errorlevel;1;
set "||=||:&if;errorlevel;1;
:: which are used like
find "NVIDIA GeForce 7900 GS" "..\d3d9.dll" %&&% %^%
(
set v.FAKE=NVIDIA GeForce 7900 GS
)^
else find "ENB" "..\d3d9.dll" %&&% %^%
(
set v.FAKE=NVIDIA GeForce 9600 GT
)^
else %^%
(
set v.FAKE=
)
Code: Select all
:: predecessors to the later version
set "or=call)&(if
set "or=call)&(if;not;errorlevel;1;if
Code: Select all
:: inverted use of errorlevel that DOES NOT WORK
set "if=call&(if
set "or=call;)||(if
set "then=call;)&if;not;errorlevel;1
Code: Select all
:: failed attempts at standardized parenthesis
set "(=else;(
set ")=)else^
:: which led me to discover that
if a==b (echo Y)^
else^
else^
else (echo N)
:: works just fine; all those ELSEs get compacted into a single ELSE
And finally, a big fat block of batch I put at the start of my most recent batch file to make sure things will work as I expect:
Code: Select all
if not n^t==nt exit
set ~x9=
if "%~x9%~x9"=="~x9" setlocal enableextensions
if "%~x9%~x9"=="~x9" exit
if not cmdextversion 2 exit
if "!~x9!~x9"=="~x9" setlocal disabledelayedexpansion
if "!~x9!~x9"=="~x9" exit
if not defined COMSPEC exit
if not defined TEMP exit
if not defined USERPROFILE exit
if not defined CD exit
2>nul set CD && exit || call;
2>nul set ERRORLEVEL && exit || call;
Queue