2

In trying to make my .zshrc neater, I stumbled over the following problem/question: "How can I run the output of another command?". While I'm sure this is a simple problem, I just don't understand what I'm doing wrong.

I want to add pip-completion to my config. For this, I need to add the output of $ pip completion --zsh to .zshrc:

$ pip completion --zsh

pip zsh completion start

function _pip_completion { local words cword read -Ac words read -cn cword reply=( $( COMP_WORDS="$words[*]"
COMP_CWORD=$(( cword-1 ))
PIP_AUTO_COMPLETE=1 $words[1] 2>/dev/null )) } compctl -K _pip_completion pip

pip zsh completion end

Now, the lines above simply don't look nice. Instead I tried adding the following line to .zshrc:

eval $(pip completion --zshrc)

However, pip completion is not being "installed" (as opposed to when I add the lines themselves in .zshrc), but I also don't get any errors.

I have a feeling zsh doesn't evaluate the # lines properly, but I'm not sure how to test it. when I run $ eval $(pip completion --zshrc) no errors pop out.

Where am I going wrong? Is there a similar alternative to evaluating the output of $ pip completion --zsh in my .zshrc?

1 Answers1

3

You need to run

eval "$(pip completion --zsh)"

Compare the output of these two commands:

echo $(pip completion --zsh)
echo "$(pip completion --zsh)"

In zsh, $VARIABLE means “take the value of VARIABLE unless it's empty”. But $(command) means “take the output of command and break it into words at whitespace”. So in eval $(pip completion --zsh), the all sequences of whitespace, including newlines, are treated as word separators. Then eval puts all of its arguments together with a space between each. But a space is not equivalent to a newline, and the code that eval executes is just one long comment line.

This is a subset of Why does my shell script choke on whitespace or other special characters?: in zsh, unlike other sh-like shells, word splitting only happens on command substitution, not on variable substitution (except in a restricted form where an empty word resulting from a variable substitution is eliminated), and no globbing happens automatically on the result of expansion. You do need double quotes in zsh around command substitution, and around variable substitution when it might result in an empty word.