This seems like it might do what you're looking for: foo() { local cur prev opts flist lastword new COMPREPLY=() cur="${COMP_WORDSCOMP_CWORD}" prev="${COMP_WORDSCOMP_CWORD-1}" lastword="${COMP_WORDS@: -1}" if $lastword =~ / then new="${lastword##*/}" # get the part after the slash lastword="${lastword%/*}" # and the part before it else new="${lastword}" lastword="" fi flist=$( command find /root/sub1/sub2/sub3/$lastword \ -maxdepth 1 -mindepth 1 -type d -name "${new}*" \ -printf "%f\n" 2>/dev/null ) # if we've built up a path, prefix it to # the proposed completions: ${var:+val} COMPREPLY=( $(compgen ${lastword:+-P"${lastword}/"} \ -S/ -W "${flist}" -- ${cur##*/}) ) return 0 } complete -F _foo -o nospace foo Notes: I think one of the keys is the nospace option I feel like I've reinvented a wheel somewhere in the function above, possibly by not using $COMP_POINT You're not (yet, at least) using $prev (which always maintains the value "foo" in my function) Readability and functionality can be improved by using $() instead of backticks You should use command to prevent running aliases and such: flist=$(command ls -1 -d I'm using find instead of ls because it's better suited You can add the slash using S with compgen instead of your awk command You can use $cur instead of $terms since you don't have to strip out spaces, but I'm using $lastword and $new (two new variables) It's not necessary to use xargs echo since an array with newlines works fine I have not tested this with directory names having spaces or newlines in them.
This seems like it might do what you're looking for: _foo() { local cur prev opts flist lastword new COMPREPLY=() cur="${COMP_WORDSCOMP_CWORD}" prev="${COMP_WORDSCOMP_CWORD-1}" lastword="${COMP_WORDS@: -1}" if $lastword =~ / then new="${lastword##*/}" # get the part after the slash lastword="${lastword%/*}" # and the part before it else new="${lastword}" lastword="" fi flist=$( command find /root/sub1/sub2/sub3/$lastword \ -maxdepth 1 -mindepth 1 -type d -name "${new}*" \ -printf "%f\n" 2>/dev/null ) # if we've built up a path, prefix it to # the proposed completions: ${var:+val} COMPREPLY=( $(compgen ${lastword:+-P"${lastword}/"} \ -S/ -W "${flist}" -- ${cur##*/}) ) return 0 } complete -F _foo -o nospace foo Notes: I think one of the keys is the nospace option I feel like I've reinvented a wheel somewhere in the function above, possibly by not using $COMP_POINT You're not (yet, at least) using $prev (which always maintains the value "foo" in my function) Readability and functionality can be improved by using $() instead of backticks You should use command to prevent running aliases and such: flist=$(command ls -1 -d... I'm using find instead of ls because it's better suited You can add the slash using -S/ with compgen instead of your awk command You can use $cur instead of $terms since you don't have to strip out spaces, but I'm using $lastword and $new (two new variables) It's not necessary to use xargs echo since an array with newlines works fine I have not tested this with directory names having spaces or newlines in them.
Thanks Dennis! That is very close to what I'm looking for. I may be able to use it with a few tweaks, or maybe even as is.
I'll see if I can apply a similar method to tcsh as well. – Jeremy Y. Oct 8 '09 at 18:20 I thought I was pretty alone to need complex completion scripts :) +1 for the code effort!
– neuro Oct 9 '09 at 16:15.
You could just make a symlink to the first interesting node in the tree. I've done this in the past when I couldn't be bothered auto-completing large directory trees.
Unfortunately the "first interesting node" can vary greatly. As the users spend time in different parts of the tree and hop around the subtrees, there is no predicting which levels they may anchor a completion attempt. Unless we link every level (seems cumbersome and unwieldy), I'm not sure links will solve it.
– Jeremy Y. Oct 7 '09 at 16:53.
My solution, which is admittedly an 800-lb hammer, was to write a perl script to handle the completion the way I wanted it to. In tcsh... complete cd 'p|1|`complete_dirs. Pl $:1 $cdpath`|/' #!
/usr/bin/perl my $pattern = shift @ARGV; my @path = @ARGV; my @list; if ($pattern =~ m! ^(/. +/|/)(.*)!) { @list = &search_dir($1,$2,undef); } elsif ($pattern =~ m!(.+/|)(.*)!
) { my $dir; foreach $dir ('. ',@path) { push(@list,&search_dir("$dir/$1",$2,$1)); } } if (@list) { @list = map { "e_path($_) } @list; print join(' ',@list), "\n"; } sub search_dir { my ($dir,$pattern,$prefix) = @_; my @list; if (opendir(D,$dir)) { my $node; while ($node = readdir(D)) { next if ($node =~ /^\. /); next unless ($node =~ /^$pattern/); next unless (-d "$dir$node"); my $actual; if (defined $prefix) { $actual = "$prefix$node"; } elsif ($dir =~ m!
/$! ) { $actual = "$dir$node"; } else { $actual = "$dir/$node"; } push(@list,$actual); } closedir(D); } return @list; } sub quote_path { my ($string) = @_; $string =~ s!(\s)! \\$1!
G; return $string; }.
I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.