Monday, June 05, 2006

CDPATH aware completion plugin for bash

Its very annoying how cd command of bash does not integrate nicely with the CDPATH variable it defines in the context of suggested completions whe the user enters TAB.

The following script addresses the issue to a large extent (naturally, with some bugs).

Just paste the following into your .bashrc and load the .bashrc as usual, either by doing ". .bashrc" in your current shell or by logging in afresh.



complete -o nospace -F expand_to_dir_list cd

expand_to_dir_list()
{
pattern=$2

if [ "`echo $pattern | grep '^\\$'`" != "" ]
then
COMPREPLY=()

#If there is a slash at the end ...
if [ "`echo $pattern | grep '/$'`" != "" ]
then
COMPREPLY[0]=`eval "echo $pattern"`
return
fi

#List env variables which begin with the specified prefix
pattern=`echo $pattern | tr -d '$'`
for setting in `env`
do
vn=`echo $setting | cut -d'=' -f1`
if [ "`echo $vn | grep "^$pattern"`" != "" ]
then
COMPREPLY[$index]=\$$vn/
index=`expr $index + 1`
fi
done

return
#pattern=`echo eval $pattern`
fi


slash_in_pattern=`echo $pattern | grep /`

if [ "$slash_in_pattern" != "" ]
then
path_prefix=`echo $pattern|sed -e 's/\\/[^\\/]*\$//'`
name_prefix=`echo $pattern|sed -e 's/^.*\\/\\([^\\/]*\\)\$/\\1/'`
else
path_prefix="."
name_prefix=$pattern
fi

p_dirs=()
n_p_dirs=0
if [ "`echo $path_prefix|grep "^/"`" != "" ]
then
p_dirs[0]=$path_prefix
n_p_dirs=1
else
#Add . to the head of list
cdpath=".:"$CDPATH
for p_dir in `echo $cdpath | tr ':' '\n' | sort -u`
do
if [ -d "$p_dir/$path_prefix" ]
then
p_dirs[$n_p_dirs]=$p_dir/$path_prefix
n_p_dirs=`expr $n_p_dirs + 1`
fi
done
fi

COMPREPLY=()

index=0
for p_dir in "${p_dirs[@]}"
do
for entry in `ls $p_dir`
do
prefixness=`echo $entry | grep "^$name_prefix.*"`
if [ -d "$p_dir"'/'"$entry" ] && [ "$prefixness" != "" ]
then
COMPREPLY[$index]=$entry/
if [ "$p_dir" != "." ]
then
COMPREPLY[$index]=$p_dir/${COMPREPLY[$index]}
fi
#Clean path
COMPREPLY[$index]=`echo ${COMPREPLY[$index]}|sed -e 's/\\/\\//\\//g' | sed -e 's/\\/\\.\\//\\//g'`

#remove a prefixing pwd , if any
pwd=`pwd|sed -e 's/\\//\\\\\\//g'`
pwd=$pwd\\/
COMPREPLY[$index]=`echo ${COMPREPLY[$index]}|sed -e "s/^$pwd//"`

index=`expr $index + 1`
fi
done
done
}

0 Comments:

Post a Comment

Subscribe to Post Comments [Atom]

<< Home