3

I would like to source my ~/.zshrc by running . with no arguments. So this:

$ .

should do this:

$ . ~/.zshrc

I would like the normal functionality of . to remain unchanged. The only difference should be when . is invoked with no arguments.

Is this possible?

I have tried a few different approaches. Here is one of them:

dot_zshrc_or_args() {
    if [[ $# == 0 ]]; then
        \. ~/.zshrc
    else
        filename=$1
        shift
        \. $filename $@
    fi
}
alias .=dot_zshrc_or_args

Here is an example showing why it does not work:

$ echo 'echo $#' > count_args.sh
$ delegate() { . ./count_args.sh }
$ delegate foo bar baz

The last command should echo 3, but it echoes 0 if the above alias for . has been defined.

The fundamental problem seems to be that . is treated specially by the shell, allowing the script that it invokes to have access to all local variables including $1, $2, and so on. So if I try to wrap . in another function, I will lose that behavior (as in the example above).

The two approaches I was thinking of were:

  1. use an alias instead of a function
  2. make it so that . is only aliased in the interactive shell, as opposed to when it is run from another function.

I can't get it to work, though, no matter what I try. Is it possible? (If not, what are the closest alternatives I could use? My end goal is to be able to quickly source my ~/.zshrc from a shell, preferably in an intuitive and easy-to-remember way.)

6

This can potentially be done by doing horrible things with accept-line:

function _accept-line() {
    if [[ $BUFFER == "." ]]; then
        BUFFER="source ~/.zshrc"
    fi
    zle .accept-line
} 

zle -N accept-line _accept-line
  • This is beautiful, and works perfectly. I especially like (1) the fact that it actually puts ~/.zshrc into my command after I've pressed RET, so it looks less mysterious, and (2) how it neatly sidesteps any possible performance implications of overriding source or .. – Radon Rosborough Nov 30 '16 at 0:55
1

Write a function for . that calls the . builtin as appropriate. Also, == is incorrect for shell numeric comparisons (test is weird like that, and needs -eq or -ne).

function . {
    if [[ $# -eq 0 ]]; then
        builtin . ~/.zshrc
    else
        builtin . "$@"
    fi
}
  • This breaks on the example I gave in the question. With . defined as you give, delegate foo bar baz echoes 1 instead of 3. – Radon Rosborough Nov 29 '16 at 23:47
  • 1
    Change delegate to pass the args, function delegate { . ./count_args.sh "$@" } or call the builtin directly function delegate { builtin . ... – thrig Nov 30 '16 at 0:11
  • Many third-party plugins rely on the argument-passing functionality of .. I cannot change all of them, so my solution to this problem will need to be one that does not change the behavior of . in any way. (In other words: I do not have control over the definition of delegate. If you want to be particular, delegate is actually the wd function defined by the wd plugin from oh-my-zsh.) – Radon Rosborough Nov 30 '16 at 0:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.