10

(This is on MacOS with zsh 5.7.1)

Here is how I load custom functions in zsh:

# Custom functions
fpath=($HOME/.zfunc $fpath)
autoload -Uz mackupbackup
autoload -Uz tac
autoload -Uz airplane
autoload -Uz wakeMyDesktop

Each function is its own file in the ~/.zfunc directory. Note this directory is symlinked into a different directory thanks to mackup.

I wrote a new function to copy the current commit hash to the clipboard. I created a file in my $fpath called ghash, wrote the function, added a new autoload line in my .zshrc and executed source ~/.zshrc.

Here's the function

# copy the commit hash of the given git reference, or HEAD if none is given
ref=$1

if [[ $ref ]]; then
  git rev-parse $1 | pbcopy
else
  git rev-parse HEAD | pbcopy
fi

After sourcing .zshrc, the function became available and it worked, but I wanted to add a line to print a confirmation that it worked:

echo "Copied $(pbpaste) to clipboard"

So I added that line, saved the file, then I sourced .zshrc again.

I ran the function again, but its behaviour didn't change!

I thought I'd done something wrong, so I kept making changes to the function and sourcing .zshrc to no effect. All in all, I re-sourced .zshrc 22 times, by which point that operation took 37 seconds to complete...

Then I realised maybe it wasn't reloading the function, so I ran zsh to start a fresh instance (which took about 1 second), and the function started working as expected!

Anyone know why source picked up my new function, but didn't update it when the function changed?

Bonus question: why'd it take longer to run source ~/.zshrc each time I ran it?

2 Answers 2

9

Sourcing an rc file rarely if ever works in practice, because people rarely write them to be idempotent. A case in point is your own, where you are prepending the same directory to the fpath path every time, which of course means that searching that path takes a little longer each time. No doubt this isn't the only place where you are doing that sort of thing, moreover.

You also do not understand autoloading correctly. As the doco states, autoloading of a function without a body happens the first time that the function is executed. Obviously, if the function is already loaded, and thus has a body, it does not get loaded again.

You need to unfunction the function before autoloading it again.

The sample .zshrc in the Z shell source contains an freload() function that does this very thing for all of the functions named as its arguments. It also does typeset -U path cdpath fpath manpath, notice.

3
  • Yes, I should've read the autoloading docs before asking this question. I read a short article about it, but assumed it would overwrite previously autoloaded headers. My bad, and thank you for the lesson! Jan 2, 2020 at 3:48
  • I just re-read your answer and decided to mark it as the answer, since it contains a solution which I was too hung over to notice before! Turns out I already typeset -U fpath path at the end of the rc file, so the slowness isn't due to that. Maybe it's because I re-source powerlevel10k each time, and it isn't idempotent 🤔. I'll have a fiddle and post another question if I can't figure it out. Thank you again! Jan 2, 2020 at 23:05
  • 4
    Powerlevel10k does nothing when your source it for the second time. As JdeBP said, don't use source ~/.zshrc. If you really want to avoid restarting zsh, use exec zsh. It's not a bullet proof way of reinitializing zsh but it's at least an order of magnitude more robust than source ~/.zshrc. Jan 6, 2020 at 22:04
5

While autoload marks a name for autoloading on first reference in zsh, it doesn't redefine any existing function with the same name should it already be defined, since the name has already been referenced once it was defined. in order to achieve what you desire, you would have to undefine the function first before sourcing .zshrc again or for something more streamline, create a wrapper function for autoload to check if any function names given are already defined and if so, undefine them before marking them for autoload again.

As to why sourcing your .zshrc became slower after each attempt, that isn't answerable without said .zshrc.

1
  • Ah yes, that makes sense. Thank you very much! Jan 2, 2020 at 3:45

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .