I have spent hours doing this.
@echo off
set list = 0 0 1 1
:loop
cls
echo Program Select
echo --------------
set "el=0"
for %%a in (%list%) do (
set /a "el+=1"
if %%a equ 0 echo "[ ] Program %el%"
if %%a equ 1 echo "[X] Program %el%"
)
echo ----------------------------------------------------
echo W = Up / S = Down / L = Toggle / H = Confirm
choice /C WSLH /N >nul
if %ERRORLEVEL% equ 1 set key=UP
if %ERRORLEVEL% equ 2 set key=DN
if %ERRORLEVEL% equ 3 set key=SL
if %ERRORLEVEL% equ 4 set key=CN
echo %key%
pause >nul
goto loop
Now the key variable works fine, and I have yet to implement scrolling, because I can't seem to get it to even render the text.
The goal is to get output like this
Program Select
--------------
[ ] Program 1
[ ] Program 2
[X] Program 3
[X] Program 4
----------------------------------------------------
W = Up / S = Down / L = Toggle / H = Confirm
But instead, I just get the Program Select and the controls. What am I missing?
Here's a more "meated-out" version of your code:
@echo off
SETLOCAL enabledelayedexpansion
:: Program names used
set "program[1]=Program one"
set "program[2]=Program two"
set "program[3]=Program three"
set "program[4]=Program four"
set /a maxprogs=4
:: symbols used for statuses
set "symbols= X"
set "symbolsc=-+"
:restart
:: Set original list status. 0=not selected, 1=selected;
set "list=0 0 1 1"
set /a cursor=1
:loop
cls
echo Program Select
echo --------------
set /a el=0
for %%a in (%list%) do (
set /a el+=1
if !el!==%cursor% (set "ds=!symbolsc:~%%a,1!") else (set "ds=!symbols:~%%a,1!")
call set "progname=%%program[!el!]%%"
echo [!ds!] !progname!
)
echo ----------------------------------------------------
choice /C WSLHQ /N /M "W = Up / S = Down / L = Toggle / H = Confirm / Q = Quit "
set /a key=%errorlevel%
if %key%==5 goto :eof
if %key%==4 goto confirm
if %key%==3 goto toggle
if %key%==2 if %cursor%==%maxprogs% (set /a cursor=1) else set /a cursor+=1
if %key%==1 if %cursor%==1 (set /a cursor=%maxprogs%) else set /a cursor-=1
goto loop
:confirm
echo Confirmed!
set "runany="
set /a el=0
for %%a in (%list%) do (
set /a el+=1
if %%a==1 (
set /a runany+=1
call set "progname=%%program[!el!]%%"
echo Run !progname!
)
)
if not defined runany echo None selected :(
timeout /t 5 /nobreak
goto restart
:toggle
set "newlist="
set /a el=0
for %%a in (%list%) do (
set /a el+=1
if !el!==%cursor% (
if %%a==0 (set "newlist=!newlist! 1") else (set "newlist=!newlist! 0")
) else set "newlist=!newlist! %%a"
)
set "list=%newlist%"
goto loop
Comments:
SETLOCAL enabledelayedexpansion allows !var! to access the changed value of var within a loop (%var% accesses the original value, before the loop started executing).
I used maxprogs so that expansion of the list is intuitive - just follow the bouncing ball...
Since the cursor is static, I used symbols to represent the non-selected/selected states and symbolsc for when the "cursor" is on the state, so + is cursor-is-here-it's-selected and - is cursor-is-here-it's-not-selected
The list usage is similar to your version - cursor is for the current cursor-line.
In the display-selections-and-prognames section, note the use of !el! to access the modified value of el within the loop
The tricky bit here is the call set "progname=%%program[!el!]%%" statement. This uses a parsing trick to get the value of the program name el. Assuming the current value of el is 2 for instance, this executes the command set "progname=%program[2]%" in a sub-shell by interpreting %% as an escaped-% and substituting for the current value of el. The subshell inherits the environment of its caller, so the destination variable is assigned from the calculated value.
I've modified the choice command to prompt with the legend, and added Q for Quit as good measure. I'd have used UDTRQ myself, for Up/Down/Toggle/Run/Quit, but something tells me you may not necessarily be using English.
I set errorlevel into key to avoid having to be particularly careful about maintaining its value, then tested key for the only 5 values of interest; on others just beep (from choice and present-again.
Quit is obvious; cursor-move simply increments or decrements cursor and checks boundary conditions for roll-around.
The other two routines are simply modifications of the display-list routine; the run displays the prognames as I have no idea whether you want to run the programs serially or in parallel.
The toggle routine uses the same technique to rebuild list whilst toggling the cursor'th element.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With