> get_drive_letters() {
> mount | grep -i '^[a-z]:' | cut -d':' -f1 | tr '[:upper:]' '[:lower:]' | sort -u
> }
Clever enough to create that function but then it didn't use it where
it would make sense. In any case that pipeline is functional but
wasteful.
${${(M)${(fL)"$(mount)"}:#[a-z]:*}%%:*}
I left out the "sort -u" because (a) the order shouldn't matter and
(b) if "mount" isn't already returning each drive uniquely I think
something is wrong.
On my system this results in `c c c c g j l m p` so I'll keep the implementation with `sort -u`.
> # Store the original completion function
> functions -c -- _normal _normal@original
OK, interesting if Claude figured that out itself.
> # Create completion functions for each drive
This isn't necessary. Just re-use _normal@original every time. You
only need a new function if you're going to change the operation, and
"functions -c" changes nothing but the name. I just threw the drive
letter in when creating the first copy to make the suffix part after
the @ more distinctive.
> _normal () {
> for drive in $(mount | grep -i '^[a-z]:' | cut -d':' -f1 | tr '[:upper:]' '[:lower:]' | sort -u); do
local drive
for drive in ${${(M)${(fL)"$(mount)"}:#[a-z]:*}%%:*}; do
> if compset -P "/${drive}/"
> then
> local opwd=$PWD ret
> cd /${drive} || return 1
> _normal@${drive}:drive "$@"
_normal@original "$@"
> ret=$?
> cd $opwd
> return ret
> fi
> done
> _normal@original "$@"
> }
I think we can fix the autocd problem in two steps:
1. Don't do the whole compset+cd dance if we already know a directory
name under the drive name
2. If we pass that hurdle and are in command position with autocd,
jump straight to _cd
"compset -P" accepts a pattern, so we can remove the loop from the
foregoing by turning the list of drive names into a pattern, which
just means joining them with (j:|:). That puts the name matched by
the pattern into $IPREFIX, so we don't need the $drive local.
That gives (harder for me to test with no windows environment, so may
need tweaking) --
_normal () {
if [[ $PREFIX != /*/*/* ]] && compset -P
"/(${(j:|:)${(M)${(fL)"$(mount)"}:#[a-z]:*}%%:*})/"
then
local opwd=$PWD ret
cd $IPREFIX || return 1
if [[ -o autocd && $compstate[context] = command ]]
then
_cd "$@"
else
_normal@original "$@"
fi
ret=$?
cd $opwd
return ret
else
_normal@original "$@"
fi
}
This works for /c/ but not for my other drives. I changed it around and now it works great:
get_drive_letters() {
mount | grep -i '^[a-z]:' | cut -d':' -f1 | tr '[:upper:]' '[:lower:]' | sort -u
}
# Store the original completion function
functions -c -- _normal _normal@original
# This autocompletes stuff like `/c/Windows`
_normal () {
if [[ $PREFIX != /*/*/* ]] && compset -P "/([$(get_drive_letters | tr -d '\n' | tr -d ' ')])/"
then
local opwd=$PWD ret
cd $IPREFIX || return 1
if [[ -o autocd && $compstate[context] = command ]]
then
_cd "$@"
else
_normal@original "$@"
fi
ret=$?
cd $opwd
return ret
else
_normal@original "$@"
fi
}