我痴迷于通过纯命令行模拟8位时代程序功能的想法。因此,我想制作一组菜单选项,这些选项可以用标称(因为箭头键没有关键点映射(左右键选择,并用Enter键确认。为了清楚起见,我写了一个工作示例请注意ANSI转义码,我用了很多,不确定浏览器中是否会显示ESC控制字符
@ECHO OFF
ECHO Chose and option with [36mZ[0m for left, [36mX[0m for right, [36mC[0m for confirm
:PICKMENU
SETLOCAL
SET menumsg="[7mExit [0m Next"
SET menumsgDef="[7mExit [0m Next"
SET menumsgNxt="[0mExit [7m Next"
:subpick
CHOICE /N /C zxc /m:[3;1H%menumsg%
IF %errorlevel% EQU 0 ECHO Just in case of errors & GOTO PICKMENU
IF %errorlevel% EQU 1 SET menumsg=%menumsgDef% & GOTO subpick
IF %errorlevel% EQU 2 SET menumsg=%menumsgNxt% & GOTO subpick
IF %errorlevel% EQU 3 GOTO confirm
:confirm
IF %menumsg% EQU %menumsgNxt% (ECHO [0mNext option is chosen & GOTO PICKMENU) ELSE (ECHO ^Exit is chosen! & TIMEOUT 2 >NUL & EXIT)
ENDLOCAL
PAUSE
当我试图将这个菜单包装在某种函数中时,我的问题就开始了,在这种函数中,每当我需要菜单或对话框时,我可以传递参数,而不是生成hoggie代码:
@ECHO OFF
REM ----So I start with setting variables with idea of argument string tokenisation on the mind----
SET $teststring=OptionOne OptionTwo OptionThree
SET /A $currentitem=1
REM ----I would use function that I found here on Stackoverflow to count amount of options in my string.----
REM ----This is magic for me, without this solution I would be using FOR loop and delims----
CALL :COUNTOPTIONS %$teststring%
:COUNTOPTIONS
SETLOCAL EnableDelayedExpansion
SET /A Count=0
:repeatme
IF NOT "%1"=="" (
SET /A Count+=1
SHIFT
GOTO :repeatme
)
ENDLOCAL & SET $optionsamount=%Count%
ECHO The number of words is %$optionsamount%
PAUSE
:PICKCURRENT
REM ----So I got maximum number of options, I guess it would be useful since by design user could stumble upon the
REM ----edge of menu by occasionaly pressing "left" or "right" controls too much. Thats how I limit the variable...
IF %$currentitem% LSS 1 SET /A $currentitem=1
IF %$currentitem% GTR %$optionsamount% SET /A $currentitem=%$optionsamount%
ECHO %$optionsamount%
REM ----This is where I completely lost it. I am trying to echo "options" string as separated items to the target location...-----
FOR /F "tokens=*" %%A IN ("%$teststring%") DO ECHO [1;1H%%A
REM ----...and echo "currently selected" item into the same place...
FOR /F "tokens=%$currentitem%" %%B IN ("%$itemstring%") DO SET $selector=[1;1H[7m%%B[0m
REM ----...and make it interactive with choice----
CHOICE /N /C zxc /m:%$selector%
IF %errorlevel% EQU 0 ECHO oops & GOTO PICKITEM
IF %errorlevel% EQU 1 SET /A "$currentitem=$currentitem-1" & GOTO PICKCURRENT
IF %errorlevel% EQU 2 SET /A "$currentitem=$currentitem+1" & GOTO PICKCURRENT
IF %errorlevel% EQU 3 GOTO confirm
PAUSE
(为了说明我在做什么,我修改了剧本结构(。
显然,我的问题是缺乏对循环和函数的理解,但到目前为止,通过ss64上的参考和强烈的谷歌搜索并没有那么有启发性。因此,我很乐意指出教育材料以及对我的代码的评论。我想强调的是,问题陈述并不意味着使用额外的库或资源工具包。
询问库和教程的推荐超出了S.O.的范围,您的代码是tl;接近睡觉时间的医生。也许我明天再看一眼。我看到的最明显的问题是,您的函数位于主运行时中,并且您从未goto
通过它们。它们应该在最终的goto :EOF
或exit /B
之后,这样它们就不会在批处理脚本的正常从上到下顺序中执行。示例:
@echo off & setlocal
call :add 5 9 sum
echo The sum is %sum%
exit /b
rem // Functions go here, below exit /b
:add <num1> <num2> <return_var>
set /a %~3=%~1 + %~2
goto :EOF
:subtract <num1> <num2> <return_var>
set /a %~3=%~1 - %~2
goto :EOF
但我想,至少目前我可能会共享一个更完整的菜单脚本,不需要ansi解释器。
<# : Batch portion
@echo off & setlocal enabledelayedexpansion
set "menu[0]=Format C:"
set "menu[1]=Send spam to boss"
set "menu[2]=Truncate database *"
set "menu[3]=Randomize user password"
set "menu[4]=Download Dilbert"
set "menu[5]=Hack local AD"
for /L %%I in (6,1,15) do set "menu[%%I]=loop-generated demo item %%I"
set "default=0"
powershell -noprofile "iex (${%~f0} | out-string)"
echo You chose !menu[%ERRORLEVEL%]!.
goto :EOF
: end batch / begin PowerShell hybrid chimera #>
$menutitle = "CHOOSE YOUR WEAPON"
$menuprompt = "Use the arrow keys. Hit Enter to select."
$menufgc = "yellow"
$menubgc = "darkblue"
[int]$selection = $env:default
$h = $Host.UI.RawUI.WindowSize.Height
$w = $Host.UI.RawUI.WindowSize.Width
# assume the dialog must be at least as wide as the menu prompt
$len = [math]::max($menuprompt.length, $menutitle.length)
# get all environment vars matching menu[int]
$menu = gci env: | ?{ $_.Name -match "^menu[(d+)]$" } | sort @{
# sort on array index as int
Expression={[int][RegEx]::Match($_.Name, 'd+').Value}
} | %{
$val = $_.Value.trim()
# truncate long values
if ($val.length -gt ($w - 8)) { $val = $val.Substring(0,($w - 11)) + "..." }
$val
# as long as we're looping through all vals anyway, check whether the
# dialog needs to be widened
$len = [math]::max($val.Length, $len)
}
# dialog must accomodate string length + box borders + idx label
$dialogwidth = $len + 8
# center horizontally
$xpos = [math]::floor(($w - $dialogwidth) / 2)
# center at top 1/3 of the console
$ypos = [math]::floor(($h - ($menu.Length + 4)) / 3)
# Is the console window scrolled?
$offY = [console]::WindowTop
# top left corner coords...
$x = [math]::max(($xpos - 1), 0); $y = [math]::max(($offY + $ypos - 1), 0)
$coords = New-Object Management.Automation.Host.Coordinates $x, $y
# ... to the bottom right corner coords
$rect = New-Object Management.Automation.Host.Rectangle `
$coords.X, $coords.Y, ($w - $xpos + 1), ($offY + $ypos + $menu.length + 4 + 1)
# The original console contents will be restored later.
$buffer = $Host.UI.RawUI.GetBufferContents($rect)
function destroy { $Host.UI.RawUI.SetBufferContents($coords,$buffer) }
$box = @{
"nw" = [char]0x2554 # northwest corner
"ns" = [char]0x2550 # horizontal line
"ne" = [char]0x2557 # northeast corner
"ew" = [char]0x2551 # vertical line
"sw" = [char]0x255A # southwest corner
"se" = [char]0x255D # southeast corner
"lsel" = [char]0x2192 # right arrow
"rsel" = [char]0x2190 # left arrow
}
function WriteTo-Pos ([string]$str, [int]$x = 0, [int]$y = 0,
[string]$bgc = $menubgc, [string]$fgc = $menufgc) {
$saveY = [console]::CursorTop
[console]::setcursorposition($x,$offY+$y)
Write-Host $str -b $bgc -f $fgc -nonewline
[console]::setcursorposition(0,$saveY)
}
# Wait for keypress of a recognized key, return virtual key code
function getKey {
# PgUp/PgDn + arrows + enter + 0-9
$valid = 33..34 + 37..40 + 13 + 48..(47 + [math]::min($menu.length, 10))
# 10=a, 11=b, etc.
if ($menu.length -gt 10) { $valid += 65..(54 + $menu.length) }
while (-not ($valid -contains $keycode)) {
$keycode = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown').VirtualKeyCode
}
$keycode
}
# for centering the title and footer prompt
function center([string]$what, [string]$fill = " ") {
$lpad = $fill * [math]::max([math]::floor(($dialogwidth - 4 - $what.length) / 2), 0)
$rpad = $fill * [math]::max(($dialogwidth - 4 - $what.length - $lpad.length), 0)
"$lpad $what $rpad"
}
function menu {
$y = $ypos
WriteTo-Pos ($box.nw + (center $menutitle $box.ns) + $box.ne) $xpos ($y++)
WriteTo-Pos ($box.ew + (" " * ($dialogwidth - 2)) + $box.ew) $xpos ($y++)
# while $item can equal $menu[$i++] without error...
for ($i=0; $item = $menu[$i]; $i++) {
$rtpad = " " * [math]::max(($dialogwidth - 8 - $item.length), 0)
if ($i -eq $selection) {
WriteTo-Pos ($box.ew + " " + $box.lsel + " $item " + $box.rsel + $rtpad `
+ $box.ew) $xpos ($y++) $menufgc $menubgc
} else {
# if $i is 2 digits, switch to the alphabet for labeling
$idx = $i; if ($i -gt 9) { [char]$idx = $i + 55 }
WriteTo-Pos ($box.ew + " $idx`: $item $rtpad" + $box.ew) $xpos ($y++)
}
}
WriteTo-Pos ($box.sw + ([string]$box.ns * ($dialogwidth - 2) + $box.se)) $xpos ($y++)
WriteTo-Pos (" " + (center $menuprompt) + " ") $xpos ($y++)
1
}
while (menu) {
[int]$key = getKey
switch ($key) {
33 { $selection = 0; break } # PgUp/PgDn
34 { $selection = $menu.length - 1; break }
37 {} # left or up
38 { if ($selection) { $selection-- }; break }
39 {} # right or down
40 { if ($selection -lt ($menu.length - 1)) { $selection++ }; break }
# letter, number, or enter
default {
# if alpha key, align with VirtualKeyCodes of number keys
if ($key -gt 64) { $key -= 7 }
if ($key -gt 13) {$selection = $key - 48}
# restore the original console buffer contents
destroy
exit($selection)
}
}
}
好吧,我在几天的不眠之夜里就自己找到了解决方案:
@ECHO OFF
:SELECTLOOP
SETLOCAL EnableDelayedExpansion
SET /A current=1
:subpick
ECHO ------
SET /A count=0
FOR /F "delims=" %%M IN ("ONE TWO THREE FOUR FIVE") DO FOR %%N IN (%%M) DO (
SET /A count+=1
SET str!count!=%%N
IF !count! NEQ !current! (ECHO %%N) ELSE (ECHO ^>%%N^<))
CHOICE /N /C zxc /m:"------"
IF %errorlevel% EQU 0 ECHO error message & GOTO SELECTLOOP
IF %errorlevel% EQU 1 set /A current-=1 & GOTO subcheck
IF %errorlevel% EQU 2 set /A current+=1 & GOTO subcheck
IF %errorlevel% EQU 3 (ECHO !current! IS CONFIRMED) & (TIMEOUT 3 >NUL)
:subcheck
CLS
IF !current! LSS 1 SET /A current=1
IF !current! GTR !count! SET /A current=!count!
GOTO subpick
PAUSE
我有一个例子,但它的很长
@echo off
mode con cols=60 lines=20
echo [40m[0m
:optionshight
title Menu Choices
cls
echo A = Left D = Right X = Select
echo ____________________________________________________________
echo.
echo.
echo.
echo.
echo.
echo The Main Menu
echo The Main Menu
echo The Main Menu
echo The Main Menu
echo The Main Menu The Main Menu
echo The Main Menu The Main Menu
echo The Main MenuThe Main Menu
echo.
echo.
echo ____________________________________________________________
echo.
echo [7mOptions[0m Menu Time Info Extras Quit
choice /c adx >nul
if %errorlevel% EQU 1 goto quithight
if %errorlevel% EQU 2 goto menuhight
if %errorlevel% EQU 3 goto options
:quithight
title Menu Choices
cls
echo A = Left D = Right [30mW = Up[0m X = Select
echo ____________________________________________________________
echo.
echo.
echo.
echo.
echo.
echo The Main Menu
echo The Main Menu
echo The Main Menu
echo The Main Menu
echo The Main Menu The Main Menu
echo The Main Menu The Main Menu
echo The Main MenuThe Main Menu
echo.
echo.
echo ____________________________________________________________
echo.
echo Options Menu Time Info Extras [7mQuit[0m
choice /c adx >nul
if %errorlevel% EQU 1 goto extrashight
if %errorlevel% EQU 2 goto optionshight
if %errorlevel% EQU 3 goto quit
:menuhight
title Menu Choices
cls
echo A = Left D = Right X = Select
echo ____________________________________________________________
echo.
echo.
echo.
echo.
echo.
echo The Main Menu
echo The Main Menu
echo The Main Menu
echo The Main Menu
echo The Main Menu The Main Menu
echo The Main Menu The Main Menu
echo The Main MenuThe Main Menu
echo.
echo.
echo ____________________________________________________________
echo.
echo Options [7mMenu[0m Time Info Extras Quit
choice /c adx >nul
if %errorlevel% EQU 1 goto optionshight
if %errorlevel% EQU 2 goto timehight
if %errorlevel% EQU 3 goto nothinghere1
:timehight
title Menu Choices
cls
echo A = Left D = Right X = Select
echo ____________________________________________________________
echo.
echo.
echo.
echo.
echo.
echo The Main Menu
echo The Main Menu
echo The Main Menu
echo The Main Menu
echo The Main Menu The Main Menu
echo The Main Menu The Main Menu
echo The Main MenuThe Main Menu
echo.
echo.
echo ____________________________________________________________
echo.
echo Options Menu [7mTime[0m Info Extras Quit
choice /c adx >nul
if %errorlevel% EQU 1 goto menuhight
if %errorlevel% EQU 2 goto infohight
if %errorlevel% EQU 3 goto time
:time
title Time
cls
echo X = Select
echo ____________________________________________________________
echo.
echo.
echo.
echo.
echo %time%
echo.
echo %date%
echo.
echo.
echo.
echo.
echo.
echo.
echo.
echo ____________________________________________________________
echo.
echo [7mBack[0m
choice /t 1 /c xq /d q>nul
if %errorlevel% EQU 1 goto timehight
if %errorlevel% EQU 2 goto time
goto time
:infohight
title Menu Choices
cls
echo A = Left D = Right X = Select
echo ____________________________________________________________
echo.
echo.
echo.
echo.
echo.
echo The Main Menu
echo The Main Menu
echo The Main Menu
echo The Main Menu
echo The Main Menu The Main Menu
echo The Main Menu The Main Menu
echo The Main MenuThe Main Menu
echo.
echo.
echo ____________________________________________________________
echo.
echo Options Menu Time [7mInfo[0m Extras Quit
choice /c adx >nul
if %errorlevel% EQU 1 goto timehight
if %errorlevel% EQU 2 goto extrashight
if %errorlevel% EQU 3 goto infopage1
:extrashight
title Menu Choices
cls
echo A = Left D = Right X = Select
echo ____________________________________________________________
echo.
echo.
echo.
echo.
echo.
echo The Main Menu
echo The Main Menu
echo The Main Menu
echo The Main Menu
echo The Main Menu The Main Menu
echo The Main Menu The Main Menu
echo The Main MenuThe Main Menu
echo.
echo.
echo ____________________________________________________________
echo.
echo Options Menu Time Info [7mExtras[0m Quit
choice /c adx >nul
if %errorlevel% EQU 1 goto infohight
if %errorlevel% EQU 2 goto quithight
if %errorlevel% EQU 3 goto extras
:infopage1
title Info
cls
echo A = Left D = Right X = Select
echo ____________________________________________________________
echo.
echo.
echo.
echo.
echo.
echo.
echo.
echo.
echo.
echo.
echo.
echo.
echo.
echo.
echo ____________________________________________________________
echo.
echo [7mBack[0m
choice /c x >nul
if %errorlevel% EQU 1 goto infohight
:options
title Options
cls
echo X = Select
echo ____________________________________________________________
echo.
echo.
echo.
echo.
echo Turn Back
echo.
echo Nothing here becuz what need to settings here?
echo.
echo.
echo.
echo.
echo.
echo.
echo.
echo ____________________________________________________________
echo.
echo [7mBack[0m
choice /c x >nul
if %errorlevel% EQU 1 goto optionshight
:quit
title bye lol
exit
:nothinghere1
title Menu
cls
echo A = Left D = Right W = Up S = Down
echo ____________________________________________________________
echo.
echo [7mNothing Here[0m Nothing Here
echo.
echo.
echo Nothing Here Nothing Here
echo.
echo.
echo.
echo.
echo.
echo.
echo.
echo.
echo.
echo ____________________________________________________________
echo.
echo Back
choice /c wasd >nul
if %errorlevel% EQU 1 goto nothinghereback
if %errorlevel% EQU 2 goto nothinghere2
if %errorlevel% EQU 3 goto nothinghere3
if %errorlevel% EQU 4 goto nothinghere2
:nothinghere2
title Menu
cls
echo A = Left D = Right W = Up S = Down
echo ____________________________________________________________
echo.
echo Nothing Here [7mNothing Here[0m
echo.
echo.
echo Nothing Here Nothing Here
echo.
echo.
echo.
echo.
echo.
echo.
echo.
echo.
echo.
echo ____________________________________________________________
echo.
echo Back
choice /c wasd >nul
if %errorlevel% EQU 1 goto nothinghereback
if %errorlevel% EQU 2 goto nothinghere1
if %errorlevel% EQU 3 goto nothinghere4
if %errorlevel% EQU 4 goto nothinghere1
:nothinghere3
title Menu
cls
echo A = Left D = Right W = Up S = Down
echo ____________________________________________________________
echo.
echo Nothing Here Nothing Here
echo.
echo.
echo [7mNothing Here[0m Nothing Here
echo.
echo.
echo.
echo.
echo.
echo.
echo.
echo.
echo.
echo ____________________________________________________________
echo.
echo Back
choice /c wasd >nul
if %errorlevel% EQU 1 goto nothinghere1
if %errorlevel% EQU 2 goto nothinghere4
if %errorlevel% EQU 3 goto nothinghereback
if %errorlevel% EQU 4 goto nothinghere4
:nothinghere4
title Menu
cls
echo A = Left D = Right W = Up S = Down
echo ____________________________________________________________
echo.
echo Nothing Here Nothing Here
echo.
echo.
echo Nothing Here [7mNothing Here[0m
echo.
echo.
echo.
echo.
echo.
echo.
echo.
echo.
echo.
echo ____________________________________________________________
echo.
echo Back
choice /c wasd >nul
if %errorlevel% EQU 1 goto nothinghere2
if %errorlevel% EQU 2 goto nothinghere3
if %errorlevel% EQU 3 goto nothinghereback
if %errorlevel% EQU 4 goto nothinghere3
:nothinghereback
title Menu
cls
echo W = Up S = Down X = Select
echo ____________________________________________________________
echo.
echo Nothing Here Nothing Here
echo.
echo.
echo Nothing Here Nothing Here
echo.
echo.
echo.
echo.
echo.
echo.
echo.
echo.
echo.
echo ____________________________________________________________
echo.
echo [7mBack[0m
choice /c wsx >nul
if %errorlevel% EQU 1 goto nothinghere3
if %errorlevel% EQU 2 goto nothinghere1
if %errorlevel% EQU 3 goto menuhight
:extras
title Menu
cls
echo X = Select
echo ____________________________________________________________
echo.
echo.
echo Quit Button is For Quit :)
echo.
echo.
echo.
echo.
echo.
echo.
echo.
echo.
echo.
echo.
echo.
echo ____________________________________________________________
echo.
echo [7mBack[0m
choice /c x >nul
if %errorlevel% EQU 1 goto extrashight