简体   繁体   中英

How can I force vi/vim to exit cleanly with status 0

When editing with vim , the normal exit code is 0. For example:

vi; echo $?

will return 0 if you just do :q immediately. However, it will return 1 (or other error codes) if you ever enter a bad command. For example, typing :aaa in vim will give the error E492: Not an editor command: aaa in vim. After that point, no matter what I do, vim will subsequently exit with status 1.

This is a problem when editing git commit messages, because if you ever make a mistake while typing (easy to do in vim ), the subsequent commit message will be thrown away. (Yes, I know there are ways to retrieve it - I don't want that hassle every time I know I made a mistake.)

The question : is there a vim command to "reset" the exit code to 0?

There is a similar question here: can i force vim to exit with 0 status . However, that one is due to using vi instead of vim , which (apparently) exits with non-zero if you search for a non-existent string. This question is specifically about vim .

Edit : Thanks for the answers here: Some additional details:

  • this is on MacOS 11.2.1.
  • I have no ~/.vimrc so I'm just falling back to the Mac-provided /usr/share/vim/vimrc , which seems pretty basic.
  • calling vi -u NONE still causes the behavior described above.
  • ( most interesting ) calling vim fixes the problem. Yes, I know I mentioned above that the other answer was using vi instead of vim , but I was thrown off by this:
$ which vi
/usr/bin/vi
$ which vim
/usr/bin/vim
$ ls -l /usr/bin/vi
lrwxr-xr-x  1 root  wheel        3 Jan  1  2020 /usr/bin/vi -> vim

And when I run either vi --version or vim --version , I get identically the same output. Does vim change its behavior depending on the calling executable name? And if so, is there something I can stick in my .vimrc to override whatever that switch is? I'd love to know. In the meantime, I can fix this with export EDITOR="vim" .

By default, Vim (and at least some other implementations of vi, such as nvi), return 0 if a "normal" error occurs, such as an invalid command or another normal user input error. It is the behavior of ed to exit nonzero in such a case, and as you've found, that behavior is generally undesirable because humans are imperfect and make many mistakes, which is why Vim doesn't do that.

Vim should exit nonzero if you use :cq , which has this behavior intentionally, as well as if certain error conditions are met (eg, you run vim -y but the display cannot be started.

It is possible you have a configuration setting or plugin that causes this behavior. You can try running with vim -u NONE -U NONE to verify this, and then isolate the problem by commenting out portions of your .vimrc . It is also possible that your Vim distributor thought this would be a desirable feature to add and patched it in for you, but you haven't mentioned your OS or source of Vim packages, so it's hard to say.

To always force a zero exit, you can try :cq 0 , but that is no more likely to work than a standard :q , since they both call the exact same function ( getout ) with the exact same value (0).

I'm seeing this behavior as well on macOS 11.6, and it only happens when invoked as vi – not vim .

Why does this happen?

If we look at vim --version :

> vim --version                                                                                                                                                 
VIM - Vi IMproved 8.2 (2019 Dec 12, compiled Aug 30 2021 06:51:40)
macOS version
Included patches: 1-2029
Compiled by root@apple.com

The macOS version here let's us know that something might be up.

Looking at vim's main.c in the Apple's open source repository ( https://opensource.apple.com/source/vim/vim-91/src/main.c.auto.html ), we find this inside the int main() function:

Unix2003_compat = 0;
if (strcmp(base,"vi")==0) {
    Unix2003_compat = COMPAT_MODE("bin/vi", "Unix2003");
} else if (strcmp(base,"ex")==0) {
    Unix2003_compat = COMPAT_MODE("bin/ex", "Unix2003");
}

and then in void getout(int exitval) :

if (exmode_active || Unix2003_compat )
    exitval += ex_exitval;

The Unix2003_compat parts here are not present in the official Vim sources .

So on the macOS version of vim, if invoked as vi or ex you'll get this error preserving behavior.

Note: The Apple URL is confusing – vim-91 really corresponds to vim 8.2, which can be checked by looking at version.h in the same repo.

Solution

Invoke vim as vim instead of as vi . In the case of git set the EDITOR environment variable to vim in your .bashrc / .zshrc / config.fish .

Alternately, install the official vim through something like Homebrew.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM