-
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path_choiceMulti.bat
More file actions
198 lines (174 loc) · 9.12 KB
/
Copy path_choiceMulti.bat
File metadata and controls
198 lines (174 loc) · 9.12 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
:: ------------------------------------------------------------------------
:: Sub-script: _choiceMulti.bat
:: Version: 1.1
:: Creation Date: 2/11/2009
:: Last Modified: 20/01/2010
:: Author: wandersick
:: Email: wandersick@gmail.com
:: Web: https://wandersick.blogspot.com
:: Github Repo: https://github.com/wandersick/ws-choice
:: Supported OS: Windows 2000 or later
:: Description: Automatically fall back to set /p for systems without choice.exe
:: Differentiate choice.exe from Win 9x and 2003/Vista/7
:: Set /p also returns errorlevels
:: Definable number of choices; for YN choices, use ChoiceYN
:: v1.1 adds support of sed and tr to filter inputs
:: For a list of supported parameters, refer to paramter /?
:: ------------------------------------------------------------------------
@echo off
setlocal
if "%~1"=="/?" (goto help) else if /i "%~1"=="" (goto help) else (goto _choiceMulti)
:help
echo.
echo :: _choiceMulti.bat by wandersick - https://wandersick.blogspot.com
echo.
echo [Usage]
echo.
echo call _choiceMulti /msg "description" [/button "choices"] [/time "sec"]
echo [/default "choice"] [/errorlevel 1-9]
echo [/choice "1" ["2"] ["3"] ["4"]...["9"]]
echo.
echo /msg - the line users see when they are asked for input
echo /button - instead of ascending numbers, users can enter any of these
echo specified to go to the choice. *1 *2
echo /time - timeout after specified seconds (used with /default) *1 *2
echo /default - default answer (used with /time) *1 *2
echo /errorlevel - outputs errorlevels just as choice.exe. Either this or
echo /choice has to be set *1 *4
echo /choice - when users makes a choice, what is carried out. Either this or
echo /errorlevel has to be set *1 *3 *4
echo.
echo *1 optional
echo *2 not applicable for "set /p" (you give up set /p support by setting it)
echo *3 /choice must be the last switch, otherwise it would not run Automatically.
echo *4 maximum supported choices: 9
:: due to arguments being %1-%9 without shift. may add more in future versions
echo.
echo [Examples]
echo.
echo 1) "1" performs "echo 1", "2" performs "echo 2":
echo.
echo :: call _choiceMulti /msg "Choose: [1,2]" /choice "echo 1" "echo 2"
echo.
echo 2) Same as 1st, except that after 5 seconds, default answer "1" is supplied.
echo.
echo :: call _choiceMulti /msg "Choose: [1,2]" /Default 1 /Time 5 /choice
echo "echo 1" "echo 2"
echo.
echo 3) Same as 1st, except button of choice 1,2 is swapped with A,B.
echo "Set /p" would fail here; ensure the target system has choice.exe.
echo.
echo :: call _choiceMulti /msg "Choose: [A,B]" /button AB /choice "echo 1"
echo "echo 2"
echo.
echo * /button is [optional]. when not set, numbering and ascending order,
echo e.g. 123456789 are assumed to keep compatibility with set /p. If set /p
echo is unneeded, then anything can be set, e.g. letters and descending order.
echo.
echo 4) This is the most common. Do nothing but errorlevels just as choice.exe.
echo.
echo :: call _choiceMulti /msg "Choose: [1,2]" /errorlevel 2
echo.
echo [Returns]
echo.
echo ^%errorlevel^% 0-9, depends on user choice.
echo.
goto :_choiceMultiEnd
:_choiceMulti
:: process arguments
if /i "%~1"=="/msg" set choiceMultiMsg=%~2
if /i "%~1"=="/time" set choiceMultiTime=%~2
if /i "%~1"=="/default" set choiceMultiDefChoice=%~2
if /i "%~1"=="/button" set choiceMultiButton=%~2
if /i "%~1"=="/errorlevel" set errBit=1&set errBitNum=%~2
:: /choice must be the last switch because %1 to %9 are shifted to contain the content of choices
if /i "%~1"=="/choice" (
set choiceBit=1
shift & goto _choiceMultiArgEnd
)
if "%~2" NEQ "" shift & goto _choiceMulti
:_choiceMultiArgEnd
set choiceMultiCount=0
if defined errBit @if defined choiceBit echo.&echo :: ERROR: /choice and /errorlevel can't be used together!&echo.&goto _choiceMultiEnd
:: automatically numbers and sets user-defined choices from /choice switch
:: e.g. /choice choice1 choice2 becomes set choiceMultiUserChoice1=choice1, set choiceMultiUserChoice2=choice2
:: make use of the 'call' technique
:: if user specifies just errorlevel outputs, supply "type nul" as the choice
if defined errBit (
@for /l %%i in (1,1,%errBitNum%) do set choiceMultiUserChoice%%i="type nul"
) else (
@for /l %%i in (1,1,9) do call set choiceMultiUserChoice%%i=%%%%i%
)
:: count number of choices and save to choiceMultiCount
for /f "usebackq tokens=1,2 delims==" %%i in (`set choiceMultiUserChoice`) do @if "%%i" NEQ "" set /a choiceMultiCount+=1
:: calculate the choiceMultiButton value for use with choice.exe (not set /p, however), if user did not specify it
if not defined choiceMultiButton @for /l %%i in (1,1,%choiceMultiCount%) do call set choiceMultiButton=%%choiceMultiButton%%%%i
:_choiceMultiStart
:: if choice.exe (win98/95/nt) exists.
:: check if user defined /time and /default
if defined choiceMultiDefChoice (@if defined choiceMultiTime set choiceMultiOpt=/T:%choiceMultiDefChoice%,%choiceMultiTime% )
choice %choiceMultiOpt%/C:%choiceMultiButton% /N "%choiceMultiMsg%" 2>nul
:: errorlevel 9009 means no choice.exe; 255 means syntax error, i.e. try the next version of choice.exe
:: 9 is the max supported choices by this batch
if %errorlevel% LEQ 9 goto _choiceMultiErrorlevel
:: if choice.exe (win2003/vista/win7) exists
if defined choiceMultiDefChoice (@if defined choiceMultiTime set choiceMultiOpt=/T %choiceMultiTime% /D %choiceMultiDefChoice% )
choice %choiceMultiOpt%/C %choiceMultiButton% /N /M "%choiceMultiMsg%" 2>nul
if %errorlevel% LEQ 9 goto _choiceMultiErrorlevel
:: if neither exists (win2000/xp)
:_choiceMultiSetP
set choiceMultiSetP=
set /p choiceMultiSetP=%choiceMultiMsg%
:: filter input to allow for " Input "
:: check if required exe exist
tr.exe >nul 2>&1
if "%errorlevel%"=="9009" set noTrOrSed=1
sed.exe >nul 2>&1
if "%errorlevel%"=="9009" set noTrOrSed=1
if not defined noTrOrSed @for /f "usebackq tokens=* delims=" %%i in (`echo "%choiceMultiSetP%"^| tr.exe -s "[:punct:][:cntrl:][:space:]" " " ^| sed.exe -e "s/^.//g" -e "s/.$//g"`) do set choiceMultiSetP=%%i
:: detects if user specified an invalid answer
set choiceMultiSetPValid=0
:: compares the token 1 of "set choiceMultiUserChoice" with user input, i.e. if choiceMultiUserChoice1==choiceMultiUserChoice1 echo token 2
for /f "usebackq tokens=1,2 delims==" %%i in (`set choiceMultiUserChoice`) do (
if "%%i"=="choiceMultiUserChoice%choiceMultiSetP%" %%~j&&set /a choiceMultiSetPValid+=1
)
:: if user chose any of the valid answers, choiceMultiSetPValid becomes 1 and the loop is ended.
if %choiceMultiSetPValid% NEQ 1 goto _choiceMultiStart
:: endlocal and exit /b must reside on the same line in order to pass the error number to exit before endlocal.
endlocal & exit /b %choiceMultiSetP%
:_choiceMultiEnd
endlocal
goto :EOF
:_choiceMultiErrorlevel
:: this is used instead of the 'smarter' way used in _choiceMultiSetP because errorlevels need to be checked in descending order
:: if not defined, skip the line, otherwise it returns error if undefined
if not defined choiceMultiUserChoice9 goto _choiceMultiErr8
:: for loop to strip off the quotes (%%~i) that wraps each choiceMultiUserChoice*
for %%i in (%choiceMultiUserChoice9%) do @if "%errorlevel%"=="9" %%~i & endlocal & exit /b %errorlevel%
:_choiceMultiErr8
if not defined choiceMultiUserChoice8 goto _choiceMultiErr7
for %%i in (%choiceMultiUserChoice8%) do @if "%errorlevel%"=="8" %%~i & endlocal & exit /b %errorlevel%
:_choiceMultiErr7
if not defined choiceMultiUserChoice7 goto _choiceMultiErr6
for %%i in (%choiceMultiUserChoice7%) do @if "%errorlevel%"=="7" %%~i & endlocal & exit /b %errorlevel%
:_choiceMultiErr6
if not defined choiceMultiUserChoice6 goto _choiceMultiErr5
for %%i in (%choiceMultiUserChoice6%) do @if "%errorlevel%"=="6" %%~i & endlocal & exit /b %errorlevel%
:_choiceMultiErr5
if not defined choiceMultiUserChoice5 goto _choiceMultiErr4
for %%i in (%choiceMultiUserChoice5%) do @if "%errorlevel%"=="5" %%~i & endlocal & exit /b %errorlevel%
:_choiceMultiErr4
if not defined choiceMultiUserChoice4 goto _choiceMultiErr3
for %%i in (%choiceMultiUserChoice4%) do @if "%errorlevel%"=="4" %%~i & endlocal & exit /b %errorlevel%
:_choiceMultiErr3
if not defined choiceMultiUserChoice3 goto _choiceMultiErr2
for %%i in (%choiceMultiUserChoice3%) do @if "%errorlevel%"=="3" %%~i & endlocal & exit /b %errorlevel%
:_choiceMultiErr2
if not defined choiceMultiUserChoice2 goto _choiceMultiErr1
for %%i in (%choiceMultiUserChoice2%) do @if "%errorlevel%"=="2" %%~i & endlocal & exit /b %errorlevel%
:_choiceMultiErr1
if not defined choiceMultiUserChoice1 echo.&echo ** Error! No choice defined.&echo.&pause&goto :EOF
for %%i in (%choiceMultiUserChoice1%) do @if "%errorlevel%"=="1" %%~i & endlocal & exit /b %errorlevel%
:: I found that when /msg contains a question mark it is considered an additional argument,
:: even if quoted, e.g. "which choice?" vs "which choice", making it inaccurate to assume a number
:: (need more investigation)