I have a menu here that you can navigate using keys using the choice command. The problem is that I want this menu to have a variable number of options. At the moment, if there
Should anyone be looking for a variable menu navigation through choice (Or Dynamic Menu for general purposes), it is easily possible to build a variable menu using choice, String concatenation and substring modification.
The below is an example script that demonstrates a macro that builds and outputs the options available for the current menu. The command to be executed on the selected option is supplied using substring modification as exampled.
@Echo off
::: ************************************************************** || Macro Definitions
::: Delayed expansion must be enabled AFTER definition of macros, and BEFORE their use.
::: Menu Building Macro
::: Usage: %Menu:$CMD=command to be executed referencing !option!%Options as String List
::: !!! Limitation: Options and Labels beginning with the same Character cannot be used within the same menu
::: Define Command/s to be executed upon selection of a string option using substring modification to replace $CMD
::: - Commands cannot use `%` or `=` characters. Selected string is accessed using the !Option! return variable
Set "Menu=Echo/!DIV!&For %%n in (1 2)Do if %%n==2 ((Set "CHCS="&For %%G in (!Options!)Do (Set "Opt=%%~G"& Set "CHCS=!CHCS!!Opt:~0,1!"&Set "Opt[!Opt:~0,1!]=%%~G"& Set "Opt=[!Opt:~0,1!]!Opt:~1!"& Echo/!Opt!))&Echo/!DIV!& For /F "Delims=" %%o in ('Choice /N /C:!CHCS!')Do (For %%C in (!Opt[%%o]!)Do (Set "OPTION=%%C"& $CMD)))Else Set Options="
::: ************************************************************** || End of Macro Definitions
Setlocal EnableExtensions ENABLEdelayedexpansion & Rem // Required for Macro Usage.
::: Build Dividing line based on actual console dimensions.
for /F "usebackq tokens=2* delims=: " %%W in (`mode con ^| findstr Columns`) do Set "Console_Width=%%%W"
Set "DIV="&For /L %%i in (2 1 %Console_Width%)Do Set "DIV=!DIV!-"
::: ************************************************************** || Script Body (Usage examples)
:MainMenu
Cls
Echo/- Call example
%Menu:$CMD=Call :!Option! TF%Title Color
Echo/- aqcuisition menu example
%Menu:$CMD=Set /A !Option!+=1%Water Food
Echo/!Option! = !%Option%!
Echo/- Goto example
%Menu:$CMD=Goto :!Option!%Title Color Exit
::: ************************************************************** || Script Break
:Title
Echo/ Title %0
Timeout 1 > Nul
::: return if Called Else (Goto :label) -Alternative option is to allow script continuation
If not "%~1"=="" (Exit /B 0)Else Goto :MainMenu
:Color
Echo/ Color %0
Timeout 1 > Nul
If not "%~1"=="" (Exit /B 0)Else Goto :MainMenu
:Exit
Echo/ Exit %0
Exit /B 0
Below is a pratical application of the above, minus the remarks, with a colortext function to add color to each menu option.
@ECHO Off & Goto :main
:ColorMenu
rem Set /A "RR=!random! %%195 + 60","GG=!random! %%195 + 60","BB=!random! %%195 + 60"
rem Set "%~1=%/E%38;2;!RR!;!GG!;!BB!m!%~1!%/E%0m"
Set "rV="& IF "!#A!"=="" (Set #A=32)
(For %%C in ("!%~1!")Do Set "rv=!rV!%/E%!#A!m%%~C%/E%0m"& Set /A "#A+=1"& IF "!#A!"=="37" (Set #A=31)) & Set "%~1=!rV!"
Exit /B 0
:main
(Set LF=^
%= empty lines above are required. =%)
For /F eol^=^%LF%%LF%^ delims^= %%A in ('forfiles /p "%~dp0." /m "%~nx0" /c "cmd /c echo(0x09"') do Set "TAB=%%A"
For /F %%a in ('echo prompt $E ^| cmd')do (Set "/E=%%a[")
Set "ChoList=0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
Set "Menu=For %%n in (1 2)Do if %%n==2 (!DIV!&Set "CH#=0"&(Set "CHCS="&For %%G in (!Options!)Do For %%i in (!CH#!)Do (Set "CHCS=!CHCS!!ChoList:~%%i,1!"&Set "Opt[!ChoList:~%%i,1!]=%%~G"& Set "Opt=%%~G" &Call :ColorMenu Opt & Nul ')Do Set "%%G=" > Nul 2> Nul ))"
Set "GetFiles=(For /F "Delims=" %%O in ('Dir /B *.$E /O:-D')Do %DEF/array%"%%~fO")"
Set "SelectFile=%DEL/array% & %GetFiles% & If "!#$E!"=="" (!DIV!&Echo/No $E files in !CD!&!DIV!&Goto :Eof)Else For %%n in (1 2)Do If %%n==2 (Set "Ext=$E"&Set "FN="&(If /I "!#$E!"=="-1" (Echo/No $E Files found. & Exit /B 0))& (For /L %%i in (0 1 !#$E!) Do If Not "!$E[%%i]!"=="" Echo/%%i:!TAB!!$E[%%i]!)&!DIV!&Echo/[%/E%36mExit%/E%0m] or Select a $E file number [%/E%36m0%/E%0m-%/E%36m!#$E!%/E%0m]:&!DIV!&Set /P "FN=FN: "&For %%v in ("!FN!")do (If /I "!FN!"=="Exit" (Exit /B 0)Else If /I "!FN!"=="E" (Exit /B 0)Else If not "!$E[%%~v]!"=="" (Set "PATH[$E]=!$E[%%~v]!"&!DIV!&Echo/!$E[%%~v]! Selected)Else (Echo/invalid file index&!DIV!& Timeout 1 /Nobreak > Nul & Goto :!rLabel! )))Else Set rLabel="
Set "GetFolders=%DEL/array% & Set "#$E="&For /F "Delims=" %%O in ('Dir /B /A:D')Do %DEF/array%"%%~fO""
Set "SelectFolder=Set "FN="&(If /I "!#$E!"=="-1" (Echo/No Folders found in !CD!.))& (For /L %%i in (0 1 !#$E!) Do If Not "!$E[%%i]!"=="" Echo/%%i:!TAB!!$E[%%i]!)&!DIV!&Echo/[%/E%36mExit%/E%0m ^| %/E%36m..%/E%0m] Select a $E number [%/E%36m0%/E%0m-%/E%36m!#$E!%/E%0m]:&!DIV!&Set /P "FN=$E #: "&For %%v in ("!FN!")do (If /I "!FN!"=="Exit" (Exit /B 0)Else If /I "!FN!"=="E" (Exit /B 0)Else If "!FN!"==".." (CD .. &!DIV!&Echo/!CD!&!DIV!&Exit /B)Else If not "!$E[%%~v]!"=="" (Set "$E=!$E[%%~v]!"&!DIV!&Echo/!$E[%%~v]! Selected)Else (Echo/invalid index&!DIV!& Timeout 1 /Nobreak > Nul & Goto :Dir ))"
Set "Do=Set "FN="&If /I "!Option!"=="Exit" (Goto :Eof)Else IF /I "!Option!"=="Ren" (For %%P in ("!Path[$E]!")Do (Set /P "FN=New Name: " & If "!FN!"=="" (!DIV!%/E%31mFilename required%/E%0m&!DIV!& Goto :!rLabel!)Else If Not exist "!FN!.$E" (Ren %%~nxP !FN!.$E)Else (!DIV!&Echo/%/E%31m"!FN!.$E" Already exists.%/E%0m&!DIV! & Goto :!rLabel!)) & !DIV!&Echo/%/E%32mRename Succesful.%/E%0m&!DIV! & Goto :!rLabel!)Else IF /I "!Option!"=="View Info" (Echo/Modified:!TAB!!TAB!Size:!TAB!Attribs:!TAB!Location:&!DIV! & For %%I in ("!Path[$E]!")Do (Echo/%%~tI!TAB!%%~zI!TAB!%%~aI!TAB!%%~dpI))Else (For %%i in ("!Path[$E]!")Do IF /I Not "!Option!"=="View Info" Echo/[!Option!] !Path[$E]!&!DIV!&!Option! "%%~i")"
Set "Wait= Echo/&!DIV!&For %%n in (1 2) Do If %%n==2 (Set "$S=Str"& Call :ColorMenu $S & Echo/!$S!&!DIV! & Timeout !TO! > Nul 2> Nul )Else Set TO="
Setlocal EnableDelayedExpansion
for /F "usebackq tokens=2* delims=: " %%W in (`mode con ^| findstr Columns`) do Set "Console_Width=%%%W"
Set "DIV="&For /L %%i in (2 1 %Console_Width%)Do Set "DIV=!DIV!-"
Set "DIV=Echo/%/E%33m!DIV!%/E%0m"
If exist "%userprofile%\Desktop\" (Set "SourceDir=%userprofile%\Desktop\") Else (Set "SourceDir=%~dp0")
PUSHD "%SourceDir%" && cls || (Echo/You lack write permission in %~dp0 & Exit /B 1)
%Wait:Str=[!CD!]%0
:menu
Title %~n0
%Menu% Exit "Dir Change" Batch Text Vbs Cls "All Files" "User specified command" "Attribs"
If /I "!Option!"=="Exit" (POPD & Endlocal & Endlocal & Goto :Eof) Else If "!Option!"=="Cls" (Cls)Else Call :!Option! 2> Nul
Set "#A=32"
%Wait:Str=!CD!%0
%DEL/array:$E=Bat% & %DEL/array:$E=Txt% & %DEL/array:$E=Vbs%
Goto :menu
:Dir Change
%GetFolders:$E=DirPath%
%SelectFolder:$E=DirPath%
PUSHD "%DirPath%"
Exit /B
:Batch
%SelectFile:$E=Bat%Batch
(%Menu% "Exit /B" Type Call "Start """ "Ren" "Del /P" Notepad.exe "View Info" "User Specified Command") && If "!Option!"=="User Specified Command" ( Call :!Option! 2> Nul )Else %Do:$E=Bat%
%Wait:Str=Continue %50
Goto :Batch
:Text
%SelectFile:$E=Txt%Text
(%Menu% "Exit /B" Type "Ren" "Del /P" Notepad.exe "View Info" "User Specified Command") && If "!Option!"=="User Specified Command" ( Call :!Option! 2> Nul )Else %Do:$E=Txt%
%Wait:Str=Continue.%50
Goto :Text
:Vbs
%SelectFile:$E=Vbs%Vbs
(%Menu% "Exit /B" Type "Ren" "Del /P" "Start """ Notepad.exe "View Info" "User Specified Command") && If "!Option!"=="User Specified Command" ( Call :!Option! 2> Nul )Else %Do:$E=Vbs%
%Wait:Str=Continue.%50
Goto :Vbs
:All Files
Set "Spacer= "
Echo/%/E%4m%/E%32mModified:%TAB%%TAB%%/E%90mSize:%TAB%%TAB%%/E%31mAtrribs:%TAB%%/E%34mType:%TAB%%/E%36mName:%/E%0m&Echo/
For /F "Delims=" %%G in ('Dir /B *.* /O:-D /T:W /A:-D') Do (
SETLOCAL DISABLEdelayedExpansion
Set "T=%%~tG" & Set "S=%%~zG%Spacer%" & Set "A=%%~aG%Spacer%" & Set "X=%%~xG%Spacer%" & Set "N=%%~nG"
SETLOCAL ENABLEdelayedExpansion