Search code examples
batch-filedirectorymenu

Batch file - would like to display a menu of folders in 3 columns


1-column code is below. I'd like to expand "char" to 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz and then be able to display the options in 3 columns (21 items, 21 items, 20 items). Folder names over a certain length would have to be truncated. With 3 columns and potentially long folder names, long folder names would have to be truncated in the menu.

rem Set the number of lines per page, max 29
set "pageSize=29"
set "char=0123456789ACDEFGHIJKLMNOPQRSTUVWXYZ"

rem Load current directory contents
set "numNames=1"
for /D %%a in (*.) do (
   set /A numNames+=1
   set "name[!numNames!]=       %%a"
)

cd ..
set /A numPages=(numNames-1)/pageSize+1

rem Show directory contents, one page at a time
set start=2
:ShowPage
set /A page=start/pageSize+1, end=start+pageSize-1
if %end% gtr %numNames% set end=%numNames%
cls
cd %folder%
echo Page %page%/%numPages% of %CD%
echo/
set "base=1"
set /A lastOpt=pageSize+base, j=base
for /L %%i in (%start%,1,%end%) do (
   for %%j in (!j!) do echo     !char:~%%j,1! -  !name[%%i]!
   set /A j+=1
)

rem Assemble the get option message
set "mssg= (B - Back): "
if %end% lss %numNames% (
   if "%mssg%" equ " (B - Back): " (set "mssg= (") else set "mssg=%mssg%, "
   set "mssg=!mssg!Z=Next page"
)
if "%mssg%" neq " (B - Back): " set "mssg=%mssg%): "

:GetOption
choice /C 0123456789ACDEFGHIJKLMNOPQRSTUVWXYZB /N /M "Choice%mssg%"

I've found batch file solutions to browse files/folders with GUI, but I don't want to do a call to GUI (Explorer) because I'd like to keep everything on the keyboard (slows progress down to switch back and forth between mouse and keyboard all the time).


Solution

  • @ECHO OFF
    SETLOCAL ENABLEDELAYEDEXPANSION
    rem Set the number of lines per page, max 29
    set /a pageSize=29
    :: my pagewidth
    SET /a pagewidth=120
    SET "choicenames=z0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxy"
    
    
    :: remove variables starting #
    FOR /F "delims==" %%e In ('set # 2^>Nul') DO SET "%%e="
    FOR /L %%e IN (1,1,%pagewidth%) DO SET "#spaces=!#spaces! "
    
    :: Read dirnames to #nn, count to #entries
    
    FOR /d %%e IN ("%~1\*.") DO SET /a #entries+=1&SET "#!#entries!=%%e"
    SET /a #entries+=1&SET "#!#entries!=z Quit."
    SET /a #columns=(#entries + pagesize - 1) / pagesize
    SET /a #rows=(#entries + #columns - 1)/#columns
    SET /a #columnwidth=(pagewidth/#columns) - 3
    SET "#choices=z"
    
    FOR /L %%e IN (1,1,%#entries%) DO (
     rem column contents - max length + terminal spaces 
     IF %%e neq %#entries% (
      SET "#%%e=!#%%e:~-%#columnwidth%!%#spaces%"
      SET "#%%e=!choicenames:~%%e,1! !#%%e:~0,%#columnwidth%!"
      SET "#choices=!#choices!!choicenames:~%%e,1!"
     )
    )
    
    FOR /L %%e IN (1,1,%#rows%) DO (
     SET /a cols=%%e + %#rows% 
     SET /a #line=%%e + (%#rows% * 2^)
     SET "cols=!cols! !#line!"
     SET "#line=!#%%e!"
     FOR %%y IN (!cols!) DO IF DEFINED #%%y SET "#line=!#line! !#%%y!"
     ECHO !#line!
    )
    
    IF %#entries% gtr 36 (
     choice /cs /c %#choices%
    ) ELSE (
     choice /c %#choices%
    )
    
    IF ERRORLEVEL 2 (
     ECHO ERRORLEVEL is %ERRORLEVEL%
     SET /a #choices=%ERRORLEVEL%-1
     CALL SET "userchoice=%%#!#choices!%%"
     ECHO choice made : !userchoice:~2!
    ) ELSE ECHO QUIT!
    
    GOTO :EOF
    

    This should be a self-adjusting menu.

    I chose to make the QUIT choice consistently z