Search code examples
zshzsh-completion

Changing a default Zsh completion function


I noticed that tab completion for the source command in Zsh tries to complete a LOT of files. Maybe everything in $PATH? I tried using a blank .zshrc file to make sure it wasn't anything in there.

ubuntu% source d
zsh: do you wish to see all 109 possibilities (16 lines)?

I did find this file that seems to control that: /usr/share/zsh/functions/Completion/Zsh/_source

#compdef source .

if [[ CURRENT -ge 3 ]]; then
  compset -n 2
  _normal
else
  if [[ -prefix */ && ! -o pathdirs ]]; then
    _files
  elif [[ $service = . ]]; then
    _files -W path
  else
    _files -W "(. $path)"
  fi
fi

If I change the line in that last "else" statement from _files -W "(. $path)" to _files, it works the way I want it to. The tab completion only looks at files & directories in the current dir.

It doesn't seem like altering this file is the best way to go. I'd rather change something in my .zshrc file. But my knowledge of Zsh completions is a bit lacking and the searching I've done thus far hasn't led me to an answer for this.


Solution

  • Maybe everything in $PATH?

    Yes, that is correct. It offers those, because source will search your the current dir and your $PATH for any file name you pass it.

    To apply your change without modifying the original file, add this to your .zshrc file after calling compinit:

    compdef '
    if [[ CURRENT -ge 3 ]]; then
      compset -n 2
      _normal
    else
      _files
    fi
    ' source
    

    This tells the completion system to use the inline function you specified for the command source (instead of the default function).

    Alternatively, to see file completions for the current dir only, you can type

    $ source ./<TAB>