6

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.)

2 Answers 2

9

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
1
  • 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 .. Commented Nov 30, 2016 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
}
3
  • This breaks on the example I gave in the question. With . defined as you give, delegate foo bar baz echoes 1 instead of 3. Commented Nov 29, 2016 at 23:47
  • 1
    Change delegate to pass the args, function delegate { . ./count_args.sh "$@" } or call the builtin directly function delegate { builtin . ...
    – thrig
    Commented Nov 30, 2016 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.) Commented Nov 30, 2016 at 0:36

You must log in to answer this question.

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