0

see the following session in dash:

$ printf "foo\nbar\n" > testfile
$ cat testfile
foo
bar
$ vim -E testfile <<-EOS
> 1
> s/foo/baz/
> x
> EOS
$ echo $?
1
$ cat testfile
baz
bar
$ vim -E testfile +'1' +'s/baz/foo/' +'x'
$ echo $?
0
$

I use ex-mode of vi for exchaning the string foo with the string baz by using a here-document. Apparently that works. But nevertheless vim is still existing with an exit code of 1.

I then exchange the baz with foo again by giving the commands directly on the commandline to vim. That works too and returns with exit code of 0 (as expected).

What is the reason the here-document is always returning with an exit code of 1?

That even happens if I do not edit the file:

$ vim -E testfile <<-EOS
> 1
> p
> q
> EOS
foo
$ echo $?
1
$ 

What's going on there?

  • Does this also happen, when you call vim --clean -E testfile <<EOF ...? You could also try to run vim -V9 -E testfile <<EOF.... In my case the problem is produced by a BufWrite autocmd that is not properly parsed. – Ralf Mar 18 '19 at 19:20
3

This is a interesting question and I'm not sure I fully understand what is going on. So here are my findings based on my Vim setup.


My setup contains some plugins (mainly self written) installed in ~/.vim/pack/.../start. These plugins all require Vim to run in nocompatible mode (see :help 'compatible').

I looked at two different scenarios:

  1. run vim -E testfile and enter the commands manually
  2. run vim -E testfile <<-EOS... with a here document as in your question

In the first case Vim exists with 0 in the second with 1.

By running scenario 2 with -V9 I found that one of my plugins has an autocmd for the BufWritePre event and that the code of the called function is not parsed correctly. This error happens, as Vim is running in compatible mode.

From the verbose output of Vim I can see, that my ~/.vim/vimrc is not loaded, but all my plugins are loaded. This explains why vim is in compatible mode.

Investigating scenario 1 shows, that my ~/.vim/vimrc is loaded and hence Vim runs in nocompatible mode. In that case everything works fine.

Why is my vimrc only loaded in scenario 1?

My interpretation is, that Vim detects that input is from a terminal. In that case I could enter visual at the ex-prompt to switch to "normal" Vim. So Vim is preparing for that.

In scenario 2 Vim detects, that input is not a terminal (it's the here-document) and it is not possible to switch to visual. Even if you add visual to your here-document, Vim will not switch to visual (it can't as it has no access to terminal input).

Why are all the plugins loaded?

To be honest: I don't know. I think that it is fair to assume, that most plugins need Vim to run in nocompatible mode. So it doesn't make sense to load them.

Workaround

In my case everything works smooth if I force Vim to run in nocompatible mode by adding the option -N:

$ vim -N -E testfile <<-EOS
> 1
> s/foo/baz/
> x
> EOS
| improve this answer | |
  • Yes! You are right! If I run vim with --clean or with -u NONE or with -N it is working correctly. It seems like your assumption is correct. When running with -V9 I see that vim-yoink is adding an autocmd which may lead to that problem. I find this behaviour quite strange. I actually assumed that vim -E would start in compatible mode without parsing the .vimrc and without any plugins. It seems I was quite wrong. But your interpretation sounds very reasonable to me. Because I could switch to :vi it is parsing the vimrc and loads the plugins. – radlan Mar 19 '19 at 20:27
  • Still, it doesn't make sense to me, since it is setting compatible mode. I still would expect that no vimrc would be read and no plugins loaded for the same reason, compatible is set. – radlan Mar 19 '19 at 20:32
  • I just tried with neovim and the behaviour is even worse! The have the same options -e and -E, but the behave differently and apparently have a different meaning! Additionally they introduced two other options -es and -Es. Honestly I don't really understand the difference between them. But I really dislike that they changed the behaviour of the existing options. – radlan Mar 19 '19 at 20:34
  • Vim has -e and -E and it supports -es and -Es. -Es is equivalent to -E -s and that means "extended ex-mode" and "silence". This is only mentioned in the man page of Vim, but not displayed with vim --help. Honestly I find the behavior around -E a little bit strange. You might consider to open an issue at Vims Github page. – Ralf Mar 19 '19 at 20:42
0

Let's consider this test file:

$ cat file
baz is here

Now, let's run two variations on your command:

$ vim -E file +'1' +'s/None/foo/' +'x'; echo code=$?
code=1
$ vim -E file +'1' +'s/baz/foo/' +'x'; echo code=$?
code=0

Apparently, the exit code is 0 if the substitute command succeeds in making a substitution and 1 otherwise.

Let's try this again but looking at the difference between q and x as a means of exiting:

$ cat file
foo is here
$ vim -E file <<-EOS
1
s/foo/bar/
q
EOS
$ echo $?
1
$ vim -E file <<-EOS
1
s/foo/bar/
x
EOS
$ echo $?
0

If a change was made to the file but vim was exited with q leaving the changes unsaved, the exit code is 1. If the changes were saved with x, then the exit code is 0 (success). Using q! to exit while purposefully discarding changes, however, produces success (exit code 0):

$ cat file
foo is here
$ vim -E file <<-EOS
1
s/foo/bar/
q!
EOS
$ echo $?
0
| improve this answer | |

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.