这是您的代码的更“充实”的版本:
@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
评论:
SETLOCAL enabledelayedexpansion 允许!var! 在循环中访问var 的更改值(%var% 在循环开始执行之前访问原始 值)。
我使用了maxprogs,以便直观地扩展列表 - 只需跟随弹跳球...
由于光标是静态的,我使用symbols 表示非选中/选中状态,symbolsc 表示“光标”处于状态时,所以+ 是 cursor-is-here-it's -selected 和 - 是 cursor-is-here-it's-not-selected
list 用法与您的版本相似 - cursor 用于当前光标行。
在 display-selections-and-prognames 部分,注意使用!el! 来访问循环内el 的修改值
这里比较棘手的是call set "progname=%%program[!el!]%%" 语句。这使用解析技巧来获取程序名称el 的值。例如,假设el 的当前值为2,这将通过将%% 解释为转义-% 并替换current,在子shell 中执行命令set "progname=%program[2]%" > el 的值。子shell继承其调用者的环境,因此目标变量是根据计算值分配的。
我已经修改了choice 命令以使用图例进行提示,并添加 Q 表示退出作为很好的衡量标准。我自己会使用 UDTRQ 来表示 Up/Down/Toggle/Run/Quit,但有些事情告诉我你可能不一定使用英语。
我将errorlevel 设置为key 以避免在维护其值时必须特别小心,然后测试key 中仅有的5 个感兴趣的值;其他人只需发出哔哔声(来自choice 并再次出现。
退出很明显; cursor-move 只是增加或减少 cursor 并检查边界条件以进行回滚。
另外两个例程只是对显示列表例程的修改; run 显示程序名称,因为我不知道您是要串行还是并行运行程序。
toggle 例程使用相同的技术重建list,同时切换cursor'th 元素。