@ECHO OFF
SETLOCAL
REM title Password
set Pass=
set Letters=#abcdefghijklmnopqrstuvwxyz0
:Loop
cls
echo.
echo Password: %Pass%
choice /c:%Letters:~1% /n
IF ERRORLEVEL 27 GOTO :EOF
for /l %%a in (1,1,26) do if %errorlevel%==%%a CALL set Pass=%Pass% %%Letters:~%%a,1%%
goto Loop
GOTO :EOF
Here's a how-to in batch.
The core of the method is CALL set Pass=%Pass% %%Letters:~%%a,1%%
This is a parsing trick. The argument to call is parsed as
- set
- Pass=originalvalueofpassSpace
- %Letters:~thevalueofawhenmatchwasfound,1%
So, pressing c would make errorlevel and hence %%a = 3 when matched, so the %letters:~%%a,1% would be %letters:~3,1%
Using batch substringing. %letters:~3,1% means take the substring of letters, from position 3 for 1 character.
The substring syntax is
%var:~start,length% if start >=0 and length >0
%var:~start,endpos% if start >=0 and endpos <0
%var:~start,length% if start <0 and length >0
%var:~start,endpos% if start <0 and endpos <0
- length/endpos may be omitted. If omitted, the substring is "from the start position to the end"
% may be ! for delayedexpansion mode
But here's the difficulty: this substring method starts counting at 0 and we have errorlevel for the letter c = 3. Using substringing, a=0,b=1,c=2,...
So we cheat by adding an extra character at the beginning of letters. Using this extra character, the letter produced by %letters:~3,1% is c as desired. I chose # - but any character would do.
Then we restore the errorlevel output from choice by using the substring of letters starting at position 1 (which is the original substring you used.)
Last little change is that I added an extra character to the end. I chose 0 and it's used as the exit character.
On entering 0, errorlevel will be 27, so we check for that value explicitly. If a 0 is entered, just exit from the procedure (it can be any label, of course) otherwise, it must be 1..26 so go check the alphabet.