103

After installing new software, an already opened terminal with zsh won't know about the new commands and cannot generate auto-complete for those. Apparently opening a new terminal fix the problem, but can the index (or whatever you call it) be rebuilt so that auto-complete will work on the old terminal?

I tried with compinit but that didn't help. Also, is there a way that is not shell-dependent? It's nice to have a way to verify the answer as well (except for uninstalling something and reinstalling it).

What I mean is after typing a few characters of a command's name, I can press Tab, and zsh should do the rest to pull up the full name.

Braiam
  • 35,991
phunehehe
  • 20,240
  • 1
    There are two types of auto-completion you could mean when you say that an existing shell “cannot generate auto-complete for [the new commands]”:

    “command completion”—trying to get the shell to suggest the new command’s name when completing in the command position, and “argument completion”—trying to get the shell to suggest options/arguments for the new command once you have already typed its name.

    Which is giving you problems?

    – Chris Johnsen Sep 17 '10 at 11:00
  • 1
    Good question! I'd always just assumed it couldn't be done, I didn't think to check – Michael Mrozek Sep 17 '10 at 14:13
  • 1
    offtopic - people are so fickle 4 people favorited but only 2 upvote... I find it odd how few people upvote things. – xenoterracide Sep 17 '10 at 15:08
  • @Chris I mean after typing a few characters of a command's name and press tab, zsh should do the rest and pull up the full name. – phunehehe Sep 17 '10 at 15:26
  • @xeno I noticed that too; it's pretty unusual to favorite something but not upvote it – Michael Mrozek Sep 17 '10 at 17:43

3 Answers3

103

To rebuild the cache of executable commands, use rehash or hash -rf.

Make sure you haven't unset the hash_list_all option (it causes even fewer disk accesses but makes the cache update less often).

If you don't want to have to type a command, you can tell zsh not to trust its cache when completing by putting the following line in your ~/.zshrc¹:

zstyle ":completion:*:commands" rehash 1

There is a performance cost, but it is negligible on a typical desktop setting today. (It isn't if you have $PATH on NFS, or a RAM-starved system.)

The zstyle command itself is documented in the zshmodule man page. The styles values are documented in the zshcompsys and zshcompwid man pages, or you can read the source (here, of the _command_names function). If you wanted some readable documentation… if you find some, let me know!

¹ requires zsh≥4.3.3, thanks Chris Johnsen

  • 3
    Either rehash incantation should enable command-name completion of “new commands” in shells that were previously fully hashed. Setting PATH (or path) will also cause a rehash; thus PATH="$PATH" would also do the job.

    HASH_LIST_ALL is shown as a default in my documentation.

    – Chris Johnsen Sep 17 '10 at 11:13
  • That's the answer for me. – BaiJiFeiLong Sep 02 '19 at 03:38
  • I have zsh 5.8 and the zstyle command does not work for me upon modifying a completion file. – xeruf Jun 24 '21 at 11:47
  • After installing package "some-cmd", hash -r makes the command name completable, but its parameter completions are still missing, despite being added together with the (brew/deb/apk/...) package. The only way I can make it happen is to exit the shell and start a new session. – conny Dec 03 '21 at 09:18
  • @conny Indeed neither bash nor zsh detects newly added command completions on the fly. You can run exec zsh (or exec bash as applicable) to completely reload the shell configuration, but keep the terminal and environment. Exactly what this does to your history (keep recent entries in the same order, or merge in the history from other terminals) depends on the shell configuration. – Gilles 'SO- stop being evil' Dec 03 '21 at 09:22
17

If you are having problems getting “argument completion” working for the new commands then compinit is probably the command you need, however it has a caching mechanism that might be causing your problem.

The documentation for my version (4.3.10) says that compinit uses a cached “dump file”, .zcompdump, to store compiled completion functions to speed up subsequent invocations. It only invalidates the dump file when it notices a change in the number of completion files (fpath element files that start with #compdef … or #autoload …). Presumably installing new software would change the number of such completion files (assuming that it also installed its zsh auto-complete files in the right place), so I would expect a plain compinit to work. If you are in a situation where it does not work you may need to bypass or manually invalidate the dump file.

To skip using the dump file, use compinit -D; this will only affect the current shell.

To rebuild the dump file, remove it and rerun compinit:

rm -i ${ZDOTDIR:-${HOME:?No ZDOTDIR or HOME}}/.zcompdump &&
compinit

This will affect the current shell, existing shells that run plain compinit, and any future shells.

Chris Johnsen
  • 20,101
  • Some zsh frameworks like zim allow the use of per-host dump files. In that case, also remove $zcompdump_file together with .zcompdump. – sebastian Sep 27 '18 at 08:55
9

I have found that when dealing with/developing completions that live in a file with a #compdef _foo foo that I need to use upon each edit:

unfunction _foo && compinit

in order to see the updated foo command completing with the updated changes.