Commit 2339760e authored by Volker Hilsheimer's avatar Volker Hilsheimer

Support flags followed by free parameter

Clean the code up a bit while at it.
parent b290c88d
@echo off
setlocal
setlocal enabledelayedexpansion
set args=pos1 pos2 --param1 value1 --param2 value2 pos3 --flag1 --param3 value3 --array "a 1" --array "a 2" --flag2 --array a3 "pos 4" --flag3 -- pass "pass through" --pass
set /A errors=0
set debug=false
if "%1" == "--debug" (
set debug=true
shift
set args=%*
)
call ..\util\parse-opts.cmd %args%
if "%debug%" == "true" (
echo Positional: !POSITIONAL[@]!
for %%p in (!POSITIONAL[@]!) do echo - %%p
echo Flags: !FLAGS[@]!
for %%f in (!FLAGS[@]!) do echo - %%f
echo Params: !PARAMS[@]!
for %%p in (!PARAMS[@]!) do echo - %%p: !PARAM_%%p!
echo Pass-through: !PASSTHROUGH!
exit /B
)
call :assert "!POSITIONAL[@]!" "pos1 pos2 pos3 pos 4"
call :assert "!POSITIONAL[#]!" 4
call :assert "!POSITIONAL[0]!" pos1
call :assert "!POSITIONAL[1]!" pos2
call :assert "!POSITIONAL[2]!" pos3
call :assert "!POSITIONAL[3]!" "pos 4"
call :assert "!FLAGS[@]!" "flag1 flag2 flag3"
call :assert "!FLAGS[#]!" 3
call :assert "!FLAG_flag1!" true
call :assert "!FLAG_flag2!" true
call :assert "!FLAG_flag3!" true
call :assert "!FLAG_flag4!" ""
call :assert "!PARAMS[@]!" "param1 param2 param3 array"
call :assert "!PARAMS[#]!" 4
call :assert "!PARAM_param1!" "value1"
call :assert "!PARAM_param2!" "value2"
call :assert "!PARAM_param3!" "value3"
call :assert "!PARAM_array!" "a 1"
call :assert "!PARAM_array[@]!" "a 1 a 2 a3"
call :assert "!PARAM_array[0]!" "a 1"
call :assert "!PARAM_array[1]!" "a 2"
call :assert "!PARAM_array[2]!" "a3"
call :assert "!PASSTHROUGH[@]!" "pass pass through --pass"
call :assert "!PASSTHROUGH[#]!" 3
call :assert "!PASSTHROUGH[0]!" "pass"
call :assert "!PASSTHROUGH[1]!" "pass through"
call :assert "!PASSTHROUGH[2]!" "--pass"
goto :result
:assert
@echo off
echo verifying "%~1" == "%~2"
if "%~1" == "%~2" (
REM echo PASS "%~1" equals "%~2"
) else (
echo FAIL "%~1" vs "%~2"
set /A errors+=1
)
exit /B
:result
if NOT %errors% == 0 (
echo %errors% errors!
) else (
echo No errors
)
@echo off
setlocal
setlocal enabledelayedexpansion
set PARSE_OPTS_FLAGS=flag4
set args=pos1 pos2 --param1 value1 --param2 value2 pos3 --flag1 --param3 value3 --array "a 1" --array "a 2" --flag2 --array a3 "pos 4" --flag3 --flag4 pos5 -- pass "pass through" --pass
set /A errors=0
set debug=false
if "%1" == "--debug" (
set debug=true
shift
set args=%*
)
call ..\util\parse-opts.cmd %args%
if "%debug%" == "true" (
echo Positional: !POSITIONAL[@]!
for %%p in (!POSITIONAL[@]!) do echo - %%p
echo Flags: !FLAGS[@]!
for %%f in (!FLAGS[@]!) do echo - %%f
echo Params: !PARAMS[@]!
for %%p in (!PARAMS[@]!) do echo - %%p: !PARAM_%%p!
echo Pass-through: !PASSTHROUGH!
exit /B
)
call :assert "!POSITIONAL[@]!" "pos1 pos2 pos3 pos 4 pos5"
call :assert "!POSITIONAL[#]!" 5
call :assert "!POSITIONAL[0]!" pos1
call :assert "!POSITIONAL[1]!" pos2
call :assert "!POSITIONAL[2]!" pos3
call :assert "!POSITIONAL[3]!" "pos 4"
call :assert "!POSITIONAL[4]!" "pos5"
call :assert "!FLAGS[@]!" "flag1 flag2 flag3 flag4"
call :assert "!FLAGS[#]!" 4
call :assert "!FLAG_flag1!" true
call :assert "!FLAG_flag2!" true
call :assert "!FLAG_flag3!" true
call :assert "!FLAG_flag4!" true
call :assert "!FLAG_flag5!" ""
call :assert "!PARAMS[@]!" "param1 param2 param3 array"
call :assert "!PARAMS[#]!" 4
call :assert "!PARAM_param1!" "value1"
call :assert "!PARAM_param2!" "value2"
call :assert "!PARAM_param3!" "value3"
call :assert "!PARAM_array!" "a 1"
call :assert "!PARAM_array[@]!" "a 1 a 2 a3"
call :assert "!PARAM_array[0]!" "a 1"
call :assert "!PARAM_array[1]!" "a 2"
call :assert "!PARAM_array[2]!" "a3"
call :assert "!PASSTHROUGH[@]!" "pass pass through --pass"
call :assert "!PASSTHROUGH[#]!" 3
call :assert "!PASSTHROUGH[0]!" "pass"
call :assert "!PASSTHROUGH[1]!" "pass through"
call :assert "!PASSTHROUGH[2]!" "--pass"
goto :result
:assert
@echo off
REM echo verifying "%~1" == "%~2"
if "%~1" == "%~2" (
REM echo PASS "%~1" equals "%~2"
) else (
echo FAIL "%~1" vs "%~2"
set /A errors+=1
)
exit /B
:result
if NOT %errors% == 0 (
echo %errors% errors!
) else (
echo No errors
)
#!/usr/bin/env bash
declare -a args=( pos1 pos2 --param1 value1 --param2 value2 pos3 --flag1 --param3 value3 --array "a 1" --array "a 2" --flag2 --array a3 "pos 4" --flag3 -- pass "pass through" --pass )
PARSE_OPTS_FLAGS=(
flag4
)
args=( pos1
pos2
--param1 value1
--param2 value2
pos3
--flag1
--param3 value3
--array "a 1" --array "a 2"
--flag2
--array a3
"pos 4"
--flag3
--flag4
pos5
-- pass "pass through" --pass
)
declare -i errors=0
function assert()
......@@ -17,7 +35,7 @@ if [[ $1 == --debug ]]; then
debug=true
shift
unset args
declare -a args=( "$@" )
args=( "$@" )
echo "Testing ${args[*]}"
fi
......@@ -38,30 +56,37 @@ if [[ $debug == true ]]; then
exit 0
fi
assert "${POSITIONAL[*]}" "pos1 pos2 pos3 pos 4"
assert "${POSITIONAL[*]}" "pos1 pos2 pos3 pos 4 pos5"
assert "${#POSITIONAL[@]}" 5
assert ${POSITIONAL[0]} "pos1"
assert ${POSITIONAL[1]} "pos2"
assert ${POSITIONAL[2]} "pos3"
assert "${POSITIONAL[3]}" "pos 4"
assert "${POSITIONAL[4]}" "pos5"
assert "${FLAGS[*]}" "flag1 flag2 flag3"
assert "${FLAGS[*]}" "flag1 flag2 flag3 flag4"
assert "${#FLAGS[@]}" 4
assert "$FLAG_flag1" "true"
assert "$FLAG_flag2" "true"
assert "$FLAG_flag3" "true"
assert "$FLAG_flag4" ""
assert "$FLAG_flag4" "true"
assert "$FLAG_flag5" ""
assert "${PARAMS[*]}" "param1 param2 param3 array"
assert "${#PARAMS[@]}" 4
assert $PARAM_param1 "value1"
assert $PARAM_param2 "value2"
assert $PARAM_param3 "value3"
assert "$PARAM_array" "a 1"
assert "${PARAM_array[*]}" "a 1 a 2 a3"
assert "${#PARAM_array[@]}" 3
assert "${PARAM_array[0]}" "a 1"
assert "${PARAM_array[1]}" "a 2"
assert "${PARAM_array[2]}" "a3"
assert "${PASSTHROUGH[*]}" "pass pass through --pass"
assert "${#PASSTHROUGH[@]}" 3
assert "${PASSTHROUGH[0]}" "pass"
assert "${PASSTHROUGH[1]}" "pass through"
assert "${PASSTHROUGH[2]}" "--pass"
......
@echo off
REM Needs to be set in the calling script
REM setlocal ENABLEDELAYEDEXPANSION
set names=
set nameCount=0
set args=
set argCount=0
set POSITIONAL[@]=
set posCount=0
set FLAGS[@]=
set flagCount=0
set PARAMS[@]=
set PASSTHROUGH[@]=
:parseargs
if /i "%~1" == "" goto endargs
set "arg=%~1"
set "short=false"
if "!arg:~0,1!" == "-" if "!arg:~2!" == "" (
set "short=true"
)
if "!arg!" == "--" (
set "PASSTHROUGH[@]=%~2"
set "PASSTHROUGH[#]=1"
set "PASSTHROUGH[0]=%~2"
shift
goto :parseargs
)
if NOT "!PASSTHROUGH[@]!" == "" (
if NOT "%~2" == "" (
set "PASSTHROUGH[@]=!PASSTHROUGH[@]! %~2"
set "PASSTHROUGH[!PASSTHROUGH[#]!]=%~2"
set /A "PASSTHROUGH[#]+=1"
)
shift
goto :parseargs
)
if "!arg:~0,2!" == "--" (
if !argCount! LSS !nameCount! (
set args[!argCount!]=""
set /A argCount+=1
)
set names[!nameCount!]=!arg:~2!
set /A nameCount+=1
) else if "!short!" == "true" (
if !argCount! LSS !nameCount! (
set args[!argCount!]=""
set /A argCount+=1
)
set names[!nameCount!]=!arg:~1!
set /A nameCount+=1
) else (
if !nameCount! EQU !argCount! (
set POSITIONAL[!posCount!]=!arg!
if "!POSITIONAL[@]!" == "" (
set "POSITIONAL[@]=!arg!"
set /A "POSITIONAL[#]=1"
) else (
set "POSITIONAL[@]=!POSITIONAL[@]! !arg!"
set /A "POSITIONAL[#]+=1"
)
set /A posCount+=1
) else (
set "args[!argCount!]=!arg!"
set /A argCount+=1
)
)
shift
goto :parseargs
:endargs
for /L %%i in (0,1,%nameCount%) do (
set "name=!names[%%i]!"
if !name! == "" set name=
if "!name!" == "" set name=
if defined name (
set "arg=!args[%%i]!"
if !arg! == "" set arg=
if "!arg!" == "" set arg=
if not defined arg (
set "name=!name:-=_!"
set "fname=FLAG_!name!"
if "!FLAGS[@]!" == "" (
set "FLAGS[@]=!name!"
set /A "FLAGS[#]=1"
) else (
set "FLAGS[@]=!FLAGS[@]! !name!"
set /A "FLAGS[#]+=1"
)
set "FLAGS[!flagCount!]=!name!"
set "!fname!=true"
set /A flagCount+=1
) else (
set "name=!name:-=_!"
set "pname=PARAM_!name!"
for %%j in (!pname![@]) do set "value=!%%j!"
if NOT "!value!" == "" (
set "newvalue=!args[%%i]!"
for %%j in (!pname![#]) do set /A "length=!%%j!"
set /A index=!length!+1
set /A "!pname![#]=!index!"
set "!pname![!index!]=!newvalue!"
set "!pname![@]=!value! !newvalue!"
) else (
set "value=!args[%%i]!"
set "!pname!=!value!"
REM always assume we end up with an array
set "!pname![@]=!value!"
set "!pname![0]=!value!"
set /A "!pname![#]=0"
if "!PARAMS[@]!" == "" (
set "PARAMS[@]=!name!"
set /A "PARAMS[#]=1"
) else (
set "PARAMS[@]=!PARAMS[@]! !name!"
set /A "PARAMS[#]+=1"
)
)
)
)
)
REM cleanup "namespace"
set names=
set nameCount=
set arg=
set args=
set argCount=
set posCount=
set flagCount=
set short=
REM Interpret P0 and P1, set JOBDIR
set "_JOBDIR=!POSITIONAL[1]!"
set "HOST_HOME=!POSITIONAL[0]!"
call :get_username %HOST_HOME%
set "MOUNTED_HOME=C:\Users\%HOST_USER%"
if not exist %MOUNTED_HOME% SET "MOUNTED_HOME=C:\Users\host"
set JOBDIR=!_JOBDIR:%HOST_HOME%=%USERPROFILE%!
if not exist %JOBDIR% (
set JOBDIR=!_JOBDIR:%HOST_HOME%=%MOUNTED_HOME%!
)
set _JOBDIR=
set MOUNTED_HOME=
set HOST_HOME=
set JOBDIR=!JOBDIR:/=\!
exit /b
:get_username
SET "HOST_USER=%~nx1"
exit /b
@echo off
REM Needs to be set in the calling script
REM setlocal ENABLEDELAYEDEXPANSION
set names=
set nameCount=0
set args=
set argCount=0
set POSITIONAL[@]=
set posCount=0
set FLAGS[@]=
set flagCount=0
set PARAMS[@]=
set PASSTHROUGH[@]=
:parseargs
if /i "%~1" == "" goto endargs
set "arg=%~1"
set "short=false"
if "!arg:~0,1!" == "-" if "!arg:~2!" == "" (
set "short=true"
)
if "!arg!" == "--" (
set "PASSTHROUGH[@]=%~2"
set "PASSTHROUGH[#]=1"
set "PASSTHROUGH[0]=%~2"
shift
goto :parseargs
)
if NOT "!PASSTHROUGH[@]!" == "" (
if NOT "%~2" == "" (
set "PASSTHROUGH[@]=!PASSTHROUGH[@]! %~2"
set "PASSTHROUGH[!PASSTHROUGH[#]!]=%~2"
set /A "PASSTHROUGH[#]+=1"
)
shift
goto :parseargs
)
if "!arg:~0,2!" == "--" (
if !argCount! LSS !nameCount! (
set args[!argCount!]=""
set /A argCount+=1
)
set names[!nameCount!]=!arg:~2!
set /A nameCount+=1
) else (
if "!short!" == "true" (
if !argCount! LSS !nameCount! (
set args[!argCount!]=""
set /A argCount+=1
)
set names[!nameCount!]=!arg:~1!
set /A nameCount+=1
) else (
if !nameCount! EQU !argCount! (
call :add_positional !arg!
) else (
set "args[!argCount!]=!arg!"
set /A argCount+=1
)
)
)
shift
goto :parseargs
:endargs
for /L %%i in (0,1,%nameCount%) do (
set "name=!names[%%i]!"
if !name! == "" set name=
if "!name!" == "" set name=
if defined name (
set "arg=!args[%%i]!"
if !arg! == "" set arg=
if "!arg!" == "" set arg=
if not defined arg (
call :add_flag !name!
) else (
for %%f in (!PARSE_OPTS_FLAGS!) do (
if %%f==!name! (
set FORCEFLAG=true
)
)
if defined FORCEFLAG (
call :add_flag !name!
call :add_positional !args[%%i]!
) else (
set "name=!name:-=_!"
set "pname=PARAM_!name!"
for %%j in (!pname![@]) do set "value=!%%j!"
if NOT "!value!" == "" (
set "newvalue=!args[%%i]!"
for %%j in (!pname![#]) do set /A "length=!%%j!"
set /A index=!length!+1
set /A "!pname![#]=!index!"
set "!pname![!index!]=!newvalue!"
set "!pname![@]=!value! !newvalue!"
) else (
set "value=!args[%%i]!"
set "!pname!=!value!"
REM always assume we end up with an array
set "!pname![@]=!value!"
set "!pname![0]=!value!"
set /A "!pname![#]=0"
if "!PARAMS[@]!" == "" (
set "PARAMS[@]=!name!"
set /A "PARAMS[#]=1"
) else (
set "PARAMS[@]=!PARAMS[@]! !name!"
set /A "PARAMS[#]+=1"
)
)
)
)
)
)
:done
REM cleanup "namespace"
set names=
set nameCount=
set arg=
set args=
set argCount=
set posCount=
set flagCount=
set short=
REM Interpret P0 and P1, set JOBDIR
set "_JOBDIR=!POSITIONAL[1]!"
set "HOST_HOME=!POSITIONAL[0]!"
call :get_username %HOST_HOME%
set "MOUNTED_HOME=C:\Users\%HOST_USER%"
if not exist %MOUNTED_HOME% SET "MOUNTED_HOME=C:\Users\host"
set JOBDIR=!_JOBDIR:%HOST_HOME%=%USERPROFILE%!
if not exist %JOBDIR% (
set JOBDIR=!_JOBDIR:%HOST_HOME%=%MOUNTED_HOME%!
)
set _JOBDIR=
set MOUNTED_HOME=
set HOST_HOME=
set JOBDIR=!JOBDIR:/=\!
exit /b
:get_username
SET "HOST_USER=%~nx1"
exit /b
:add_flag
set "name=!name:-=_!"
set "fname=FLAG_!name!"
if "!FLAGS[@]!" == "" (
set "FLAGS[@]=!name!"
set /A "FLAGS[#]=1"
) else (
set "FLAGS[@]=!FLAGS[@]! !name!"
set /A "FLAGS[#]+=1"
)
set "FLAGS[!flagCount!]=!name!"
set "!fname!=true"
set /A flagCount+=1
exit /b
:add_positional
set POSITIONAL[!posCount!]=!arg!
if "!POSITIONAL[@]!" == "" (
set "POSITIONAL[@]=!arg!"
set /A "POSITIONAL[#]=1"
) else (
set "POSITIONAL[@]=!POSITIONAL[@]! !arg!"
set /A "POSITIONAL[#]+=1"
)
set /A posCount+=1
exit /b
......@@ -44,6 +44,10 @@ for i in ${count[@]}; do
if [[ "$arg" == '""' ]] || [[ $arg == "" ]]; then
FLAGS+=("$name")
declare "FLAG_$name"="true"
elif [[ "${PARSE_OPTS_FLAGS[@]}" =~ "$name" ]]; then
FLAGS+=("$name")
declare "FLAG_$name"="true"
POSITIONAL+=("$arg")
else
param="PARAM_$name";
value=${!param}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment