Skip to content

Instantly share code, notes, and snippets.

@leppie
Last active February 10, 2016 18:04
Show Gist options
  • Save leppie/2721371adf6bf69fa833 to your computer and use it in GitHub Desktop.
Save leppie/2721371adf6bf69fa833 to your computer and use it in GitHub Desktop.
Command line parsing in a batch file (or scripting for the mildly insane)
@echo off
setlocal EnableDelayedExpansion
:: user settings
set VERBOSE=0
set ERRORS=0
:: arg parsing settings
set ARGS=verbose debug-mode
:: implementation start
set $ARGS=%*
:: defaults
if not defined PREFIX set PREFIX=-
if not defined SEPERATOR set SEPERATOR==
if not defined SUPPORT_SHORT_FORMS set SUPPORT_SHORT_FORMS=1
if not defined SHOW_ARGS set SHOW_ARGS=0
:: get rid of =, replace with :
set X="%$ARGS%"
:sep-loop
for /f "tokens=1* delims=%SEPERATOR%" %%x in (%X%) do (
if "%%y" NEQ "" (
set $NEW=!$NEW!%%x:
set X="%%y"
goto sep-loop
) else set $NEW=!$NEW!%%x)
set $ARGS=%$NEW%
call :loop %$ARGS%
goto script
:loop
for %%m in (%ARGS%) do call :slurp %%m %1
if [%1] NEQ [] (
:: try default arg
if not defined $HANDLED call :checkdefault %1
:: odd way to restore SEPERATOR
set $TMP=%1
call set $TMP=%%$TMP::=%SEPERATOR%%%
if not defined $HANDLED call :unhandled !$TMP! 2>nul)
set $HANDLED=
shift
set param=%1
if defined param goto :loop
goto :eof
:checkdefault
set $DEFAULT=%1
if [^%$DEFAULT:~0,1%] NEQ [%PREFIX%] (
call :default %1 2>nul
if !ERRORLEVEL! EQU 0 (
set $HANDLED=1
if %SHOW_ARGS% EQU 1 echo %1))
goto :eof
:slurp
set $SLURP=%1
for /f "tokens=1,2* delims=:" %%b in ("%2") do (
if %SUPPORT_SHORT_FORMS% EQU 1 (
if %%b == %PREFIX%%$SLURP:~0,1% call :dispatch %%b %%c
if %%b == %PREFIX%%PREFIX%%$SLURP% call :dispatch %%b %%c
) else if %%b == %PREFIX%%$SLURP% call :dispatch %%b %%c)
goto :eof
:dispatch
if %SHOW_ARGS% EQU 1 (
if [%2] EQU [] echo %1
else echo %1%SEPERATOR%%2)
call :%$SLURP% %2 2> nul
IF %ERRORLEVEL% NEQ 0 echo [Error] Handler not found for "%$SLURP%"
set $HANDLED=1
goto :eof
:: implementation end
:: define arg handlers
:unhandled (optional)
:: record/log errors, cant bail here, only in :script
echo [Error] Unhandled arg: %*
set /a ERRORS+=1
goto :eof
:default (optional)
set DEFAULT=%1
goto :eof
:verbose
:: set /a VERBOSE+=%1
set VERBOSE=%1
goto :eof
:debug-mode
set DEBUG=1
goto :eof
:: finally what will be run after parsing is complete
:script
if %ERRORS% GTR 0 endlocal & exit /b 1
echo VERBOSE: %VERBOSE%
if defined DEBUG echo DEBUG: SET
if defined DEFAULT echo DEFAULT: %DEFAULT%
echo Done
:: example run with '-v=1 --debug-mode "moo poo"'
:: handles balanced quotes
endlocal
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment