Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: completion ignoring

On May 29,  4:14pm, Vincent Lefevre wrote:
} Subject: Re: completion ignoring
} On Wed, May 27, 1998 at 17:21:18 +0100, Bruce Stephens wrote:
} > That's what I understood the question to be.  And yes, isn't this how
} > zsh works right now?
} No:
} $ benchmul[TAB]
} benchmul-sparc4  benchmul-ultra1  benchmul.o
} (These 3 files are in a directory that is in my PATH.)
} -rw-r--r--   1 vlefevre lip          1388 May 29 16:12 sparc/benchmul.o

On May 29,  4:36pm, Bruce Stephens wrote:
} Subject: Re: completion ignoring
} OK, I think that's a bug in 3.0.5 then.

It's a deficiency (?) in building the command hash table, specifically.
If you enter a full (or even relative) path to a prefix of the name of
any non-executable file and then attempt to do command completion on it,
it fails.  But if you look at the output of "hash" you'll see that every
file in every directory in $PATH has been put in the table -- and command
completion reads the hash table by default, without further testing the
file permissions on the target of the hashed name.

gen_matches_files(), which is called for things not in the PATH, does do
a stat() and look for the S_IEXEC bit.

I don't think hashtable.c has changed much in 3.1.x, so this problem is
likely still present.  However, stat()-ing every file in every directory
in $PATH is probably prohibitively slow, so this could reasonably only be
handled as a special case during completion.

Unfortunately, the code that determines whether a word matches the prefix
is completely generic -- it doesn't know that the word came from the
command hash table, or even that it's a command being completed -- and it
works by adding the word to the completion list if it matches the prefix
or by ignoring it if it doesn't match the prefix.  There's no hook for
discovering that the word *might* match and then doing an extra test on
it using any other information (such as the target of the hash).  So this
behavior is unlikely to be changed anytime soon.

Of course, you could do something like

    function xhash () {
      emulate -R zsh
      setopt localoptions
      local maybe cmd i=0
      hash -f
      maybe=( $(hash -m ${1}\*${2}) )
      for cmd in ${maybe##*\=}
	[[ -x $cmd ]] && reply=( $reply ${${maybe[$i]}%\=*} )

    compctl -C -aBF -K xhash -g '*(*)'

This says, attempt to complete any aliases, builtins or functions, any
executables in the hash table, and any executable files.  The `xhash'
function fills the hash table, lists everything in it that matches the
prefix and suffix of the completion, then tests the path to which each
hashes to see if it is executable before adding it to the result.

Bart Schaefer                                 Brass Lantern Enterprises
http://www.well.com/user/barts              http://www.brasslantern.com

Messages sorted by: Reverse Date, Date, Thread, Author