Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@joerohde
Last active December 22, 2021 21:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save joerohde/446f96054b287a0dff102ace02f2d160 to your computer and use it in GitHub Desktop.
Save joerohde/446f96054b287a0dff102ace02f2d160 to your computer and use it in GitHub Desktop.
TakeCommand improved cd / cdd command
@echo off
setlocal
rem arbitrary max directories to show
set MAX=32
setarray directories[%MAX]
setarray searchResults[%MAX]
rem used to set value that conveniently escapes setlocal
setarray __CD[1]
on break goto END
on errormsg goto END
set tmpfile="%TEMP\_cds_%RANDOM.tmpfile"
>! %tmpfile
set pushcp=%_CODEPAGE
chcp 437 >nul:
rem make ^$ regex symbols easier
setdos /p@
setdos /e#
rem show directory names relative to .\ unless '/g' global search
local pathTrimPrefix
iff "%1" eq "/g" then
set pathTrimPrefix=
shift /1
elseiff "%1" eq "/?" then
goto Usage
else
rem trim it. Only root dirs have a '\' hanging. (i.e. C:\)
set pathTrimPrefix=%@rtrim[\,%_CWD]
endiff
rem hack to join all remaining arguments into 1
set param="%@unquote[%@]"
rem all \ become \\ to not break regexp processing.
rem tradeoff: can't search for special chars like this: \(x86\)
set match=%@replace[\,\\,%param]
rem escape hatch: escape special chars with '/' like this: /(x86/)
set match=%@replace[/,\,%match]
rem echo %match
set lastindex=0
gosub AppendList ^%[match]$
gosub AppendList \\%[match][^\\]+$
gosub AppendList [^\\]%[match][^\\]*$
iff %lastindex eq 0 gosub Error "No matching directories found."
iff "%@search[dialog]" ne "" then
rem source & binaries: http://andrear.altervista.org/home/cdialog.php
dialog --menu "Select Directory" 0 0 0 %@replace[#r#n,,%listing] 2>! %tmpfile
screen %@eval[%_ROWS-1] 0.
rem bail if ESC
if %? ne 0 goto END
rem strip the selected tag to a number, decrement it and store dir
set index=%@line[%tmpfile,0]
rem echo "Index: %index"
else
input /c /d /l2 Select Directory:%@unquote[%listing#r#n]choice? %%index
if %index lt 1 .or. %index gt %lastindex gosub Error "Selected index out of range."
endiff
set index=%@dec[%index]
set __CD[0]=%directories[%index]
goto END
rem subroutine for common code
:AppendList [match]
rem base command. Under the prefix path, find up to MAX directories(/ad)
rem sorted by change time, using a regular expression
local CMD
set CMD=es %pathTrimPrefix /n %@eval[%MAX-%lastindex] /ad /sort date-accessed /r
set success=%@execarray[searchResults,%CMD %match]
iff %success ne 0 gosub Error "Everything Error: %cmd %match"
rem _EXECARRAY is count of how many lines gathered, dec for index
set count=%@dec[%_EXECARRAY]
rem If there is only 1 match, and we have not found any matches before, cd directly to it
iff %count eq 0 .and. %lastindex eq 0 .and. "%searchResults[0]" ne "%_CWD" then
__CD[0]="%searchResults[0]"
goto END
endiff
rem do is inclusive '0 to 0' runs once
do index = 0 to %count (
rem store this iteration of the result to the global directory list
local directory, label
set directory=%searchResults[%index]
rem if there was a subirectory matching prefix, convert it to .\
if "%pathTrimPrefix" ne "" set label=%@replace[%pathTrimPrefix,.,%directory]
if %label eq . iterate
set directories[%lastindex]="%directory"
set lastindex=%@inc[%lastindex]
rem pretty version for dialog
set width=%@eval[%_COLUMNS-15]
set label=%directory
iff %@len[%directory] ge %width then
set label=...%@right[%@eval[%width],%directory]
endiff
rem echo %label
set line= #r#n"%@formatn[2.0,%lastindex]" "%label"
set listing=%[listing]%[line]
rem if no more room, leave the loop
if %lastindex ge %MAX leave
)
return
rem clean up, change dir if appropriate
:END
on errormsg
on break
unsetarray directories searchResults
*del /kfq %tmpfile
chcp %pushcp >nul:
endlocal
rem uh... yeah.
iff "%__CD[0]" ne "" then
pushd %__CD[0]
rem echos cd %__CD[0]
rem toast /duration=1 /expire=1 /audiostate=1 /template=4 /text1="%_CWD"
endiff
unsetarray __CD
quit
:Error [message]
echo Error: %@unquote[%message]
goto END
:Usage
local cds
set cds=%~n0
type << EndUsage
usage:
%cds: [/g #| /?] search-string
search-string can contain spaces without quotes or path seperator
%cds program files (spaces gathered to single argument)
%cds windows\sys (works as expected. '\' escaped in regex)
%cds progr.* .x86 (can contain any regex)
%cds "windows m(ail|edia)" (double quotes because of | pipe)
%cds \Pro.*/(x86/) (anti-*nix: escape regex chars with '/')
/g: search globally instead of just subdirectories of _CWD
/?: this help
to use 'dialog' text menu system, get source or binary from:
http://andrear.altervista.org/home/cdialog.php
EndUsage
goto END
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment