I'm trying to set up directory completion in tcsh and/or bash (both are used at my site) with a slight twist: for a particular command "foo", I'd like to have completion use a custom function to match the first /-delimited term to an actual subtree node, and then follow normal directory completion for any successive terms. It is sort of a combination of cdpath and completion, or I suppose a form of directory completion where the starting point is controlled by the completion script. It would work as follows:
$ foo xxx<TAB>
(custom completion function produces choices it finds at arbitrary levels in the dir tree)
xxxYYY xxxZZZ xxxBLAH ...
foo xxxYYY/<TAB>
(normal directory completion proceeds from this point on, to produce something like:)
foo scene/shot/element/workspace/user/...
We'd like to do this because we have a large production development tree (this is a CGI production facility), that shell-savvy users are navigating and jumping around in all the time. The complaint is that the upper levels of the tree are cumbersome and redundant; they just need a quick search on the first term to find possible "head" choices and do directory completion from there. It seems like programmable completion could offer a way to do this, but it is turning out to be pretty elusive.
I've made several attempts of custom bash and tcsh completion to do this, but the closest I've gotten is a form of "word completion" where the user must treat the directory levels as separate words with spaces (e.g. foo scene/ shot/ element/ workspace/ ...). I could continue hacking at my current scripts--but I've been wondering if there's something I'm not understanding--this is my first attempt to program completion, and the docs and examples are pretty thin in shell books and on the internet. If there's any completion-guru's out there that can get me on the right track, I'd appreciate it.
FWIW: here is what I've got so far (in tcsh first, then bash). Note that the static root '/root/sub1/sub2/sub3' is just a placeholder for a search function that would find different matches in different levels. If I can get that to work, I can sub in the search feature later. Again, both examples do word completion, which requires user to type a space after each matching term (I also have to remove the spaces in the function to construct an actual path, yuck!)
TCSH EXAMPLE (note the function is actually a bash script):
complete complete_p2 'C@*@`./complete.p2.list.bash $:1 $:2 $:3 $:4 $:5 $:6 $:7 $:8 $:9`@@'
#!/bin/bash --norc
# complete.p2.list.bash - Completion prototype "p2" for shotc command
# Remove spaces from input arguments
ppath=`echo $@ | sed -e 's/ //g'`
# Print basenames (with trailing slashes) of matching dirs for completion
ls -1 -d /root/sub1/sub2/sub3/$ppath* 2>/dev/null | sed -e 's#^.*/##' | awk '{print $1 "/"}'
BASH EXAMPLE:
_foo()
{
local cur prev opts flist
COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}"
# Get all command words so far (omit command [0] element itself), remove spaces
terms=`echo ${COMP_WORDS[@]:1} | sed -e 's/ //g'`
# Get basenames (with trailing slashes) of matching dirs for completion
flist=`ls -1 -d /root/sub1/sub2/sub3/${terms}* 2>/dev/null | sed -e 's#^.*/##' | awk '{print $1 "/"}' | xargs echo`
COMPREPLY=( $(compgen -W "${flist}" ${cur}) )
return 0
}
complete -F _foo foo