3

I have an alias in my zshrc so that I can edit .zshrc and then immediately source it after editing in vim, alias zshrc='vi ~/.zshrc && source ~/.zshrc, but it loads the file even when I've changed nothing. I want it to load the file only if I've used :w or :wq so that it doesn't reload it unnecessarily if I decide not to change anything.

vim ~/.zshrc exit status would be 0 if it succeeds or non-zero if it fails. Apparently there are different non-zero returns from different types of failures. What would the vim equivalent exit status be if I use :q! vs :wq in vim for example. Maybe I could focus my bash if statement on that returned exit status like if [ $? = 113 ]; then source ~/.zshrc; fi. My first thought was that it will return 0 on any successful opening of vim, but there must be some kind of way for the terminal to see what vim commands get executed inside of vim. Is there a conditional statement I can use like if [ -exec $(vim ~/.zshrc) = ":wq" ]; then source ~/.zshrc; fi. That's obviously not a real if condition that works but is there a way to accomplish something like this?

This could also be useful for instance if I'm working on a .c file and would like to see if it compiles immediately after saving and exiting vim like if [ -exec $(vim main.c) = ":wq" ]; then gcc main.c -o main && ./main; fi.

1 Answer 1

1

Vi(m) exits with status 0 unless it fails to start or it's running a script that forced an exit with a nonzero status (and I'm not sure if that one is even possible) or it is killed by a signal. You can't distinguish between :q! and :wq through the exit status.

You can check whether the file has changed between the time you start the editor and the time you exit it. You can't tell whether the file changed in this editor session, but I don't think this matters. Strictly speaking, there's no way to check whether a file has changed without keeping it open, but checking the inode change time of the same filename is close enough.

zmodload -F zsh/stat b:zstat
edit-and-source-if-changed () {
  local filename=$@[$#]
  local original_ctime="$(zstat +ctime -- $filename)" 2>/dev/null
  vim "$@" || return
  [[ -n $original_ctime ]] || return
  if [[ $original_ctime != "$(zstat +ctime -- $filename 2>/dev/null)" ]]; then
    echo source $filename
  fi
}

You can run a command when Vim exits, and you can run a command after saving a file. So from inside Vim, you could set a variable when saving a file, and then in the exit code, if that variable is set, run some command that creates a file with a fixed name. And in the code that invokes Vim, check whether that file exists. That would be more precise, but a lot more complicated than the pure shell-side solution above.

2
  • Doesn't seem to work on WSL Ubuntu Terminal, because it doesn't source .zshrc even after I edit it. I even waited 2 minutes so that the modification date would be in a different minute but that didn't do the trick. The concept of checking the time of modification is actually perfect. I didn't think of that and will look more into the zstat module. Thanks.
    – ntruter42
    Commented May 18, 2020 at 20:06
  • 1
    @ntruter42 I had made a few typos. Please try again. Commented May 18, 2020 at 20:11

You must log in to answer this question.

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