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

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 (e.g., 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.

Related

Why does my shell prompt disappear when I install vim 7.4?

I'm using CentOS 6. Since the CentOS repos have an older version of vim (7.2), I have compiled my own. However, I am having a weird issue. After running and exiting vim, I've found that my shell prompt has disappeared. Also, when I type, it does not appear in the terminal, nor does any output. What's weird is that it looks as though something is being outputted, since the cursor will move down the screen, but I can't see anything.
It must have something to do with compiling an X version, because it does not happen when I compile vim without X windows support (but I would like to have gvim, too). Here are the configuration options I supplied when compiling:
./configure --prefix=$OPT/Cellar/vim/7.4 --with-features=huge --enable-gui=auto --with-x --enable-xim
I also tried compiling without Xim. I've also tried explicitly setting --enable-gui=gtk2 (which is what gvim 7.2 from the CentOS repos uses).
I am using KDE4. The problem occurs both when running tcsh and bash. I have tried with $TERM set to both xterm and xterm-256color as well.
Additionally, running neither reset nor stty sane restores the shell to its proper behavior.
Any idea why my prompt disappears when running vim? As I missing a config flag or some other compilation issue?
I ultimately traced this down to an error in my ~/.vimrc file. I had some lines like this:
if has('gui_running')
# Gvim customization
endif
if has('gui_gtk2')
# GTK2-specific Gvim customization
endif
The second block was running every time vim loaded. Because it changed some window geometry, it ended up messing up bash; when I dropped back to bash, bash thought it only had ~53 columns to work with (and possibly some other things were messed up).
Solution: The second if block should be inside the first.

Vim - Cannot reenter Vim after executing gcc inside Vim

I am having an really annoying issue with Vim. I am learning C and everytime I invoke :!gcc something.c -o something, Vim would exit to shell outputting whatever gcc outputs. However, from here, I cannot go back to Vim. If I press ctrl-D or type exit, the terminal just says "Stopped vim something.c". However, now when I try to type "Vim something.c" again, Vim would give an error saying the file is in swap or something and that it is already opened in another session.
How do I fix this?
You want to create a makefile to help you compile and report back your errors to vim. You can do this in C and C++.
You will make a file called 'makefile' in the same dir as the file you are making. You can execute that file in vim or in the terminal and it will act the same.
You call the makefile by typing in 'make' and ':make' in vim.
More documentation
https://www.cs.swarthmore.edu/~newhall/unixhelp/howto_makefiles.html#C

vimdiff immediately becomes stopped job, crashes terminal when I try to fg it, but works with GUI

SOLVED: the problem was this line in my .vimrc:
set shell=/bin/bash\ -li
UPDATE: it appears the problem is due to my .vimrc (renaming the .vimrc to 'hide' it fixed the problem), so it probably has nothing to do with Mint.
I'm running Linux Mint 17 Cinnamon. When I run vim -d file otherversion in the terminal, I get a blank screen with
"otherversion" 18L, 218C
[1]+ Stopped vim -d file otherversion
user#machine:~/path/to/directory$ ;2R
If I do fg 1 that terminal window just closes. Also, there's no blinking cursor, though I am able to type. Same with vimdiff instead of vim -d. I've tried multiple distributions of vim, some that include the GUI, some that don't.
However, with versions that do include the GUI, if I run vim -d -g file otherversion, it works as expected.
I'd rather not depend on gvim to use vimdiff.
Any advice?
Thanks
If you need an interactive bash shell (to get your bash aliases for instance), use this code in your .vimrc instead of removing the option:
if &diff == 'nodiff'
set shellcmdflag=-ic
endif
This will only enable the interactive bash shell when not running vimdiff, so that you will have you bash aliases when running vim.
After removing the following line from my .vimrc, the problem went away:
set shell=/bin/bash\ -li
Thanks to comment from #FDinoff, the same problem at my end got solved.
The problem was "bash" command in my ~/.cshrc.
I had put that to avoid entering into bash every time after login. It was working fine until this issue started coming whenever I used to open vimdiff.
Removing ~/.vimrc didn't help me either. Then I read comment from FDinoff. There, he suggested that it could be related to shell, if "less" and "man" have also stopped working. I observed the same issue in my case, that helped me rule out the corruption in .vimrc.
After removing "bash" from my ~/.cshrc, the problem went away completely.

Discovering the cause of Vim exit status

On running:
vim /tmp/blah
:q
echo $?
I get an exit status of 1. This is breaking various things including Git. If I run vim without my vimrc:
vim -u NONE /tmp/blah
:q
echo $?
I get an exit status of 0. I use Pathogen so this also effectively disables plugins. Does anyone have a suggestion for efficiently determining the cause of the exit status? I'm aware of running Vim verbosely and logging to a file. Should I be looking for something specific in this file?
If there is a method of finding the exact line that determines the exit status I would love to know of it as searching around didn't turn much up.
Finally found this command in help: :cq[uit]. So after you do verbose logging, search for \<cq\%[uit]\>.
Update: There are also methods to alter the exit status using vim compiled with some interpreters support: at least, the following works:
python import sys
python sys.exit(1)
" (same for python3)
perl exit 1
I do not know other languages enough to write here examples of code that would quit vim with different exit status. Note also that such commands inside files sourced using :pyfile, :rubyfile and other :*file should also work, as well as this code in a modules not distributed with plugin.
I think the most efficient way here at this point is disabling plugins until you find the source of the problem.

Gvim shell problem

I have been using Gvim for quite sometime and I like it very much.
There is a problem I am facing with Gvim.
I type "shell" and go to the command line, When I press the up arrow I get some weird
symbols and I am not able to use backspace also.
The version which I am using.
VIM - Vi IMproved 7.2 (2008 Aug 9, compiled Mar 19 2009 15:27:51)
Sadly the reason this is not working is because gvim is an editor, not a terminal emulator. When yoy type :shell in gvim, you do not actually get a shell, you get some weak shell emulation. I say 'weak' because that shell emulation does not know how to deal with color codes, clear the screen or much else.
I stick to terminal vim, that way I can either use :shell, or, as is much more common, ^Z to just drop back into my shell to do something ( ^Z == suspend ) That, plus gnu-screen, plus a good shell is all the IDE I want.
Try some wrappers, e.g. Conque Shell : Run interactive commands inside a Vim buffer ;)
vim is not for such complicated things I think. you can do simple shell operation via :! or :shell, However, vim is only a good if not best editor.
What you need can be done in shell-mode of Emacs.

Resources