3

When one opens a file with an incomplete last line (File does not end with 0x0A / a new line character), the endofline option is set to false (:echo &endofline will print 0) and the [NOEOL] indicator is displayed.

If one saves such a file (:w), the new line character will be added, the [NOEOL] indicator will disappear and the filesize will grow by one byte. However, :echo &endofline will still print 0. I would expect the endofline option being in sync with the [NOEOL] indicator.

Is there a way to keep the [NOEOL] indicator in sync with the endofline option? Or alternatively to query the status of the [NOEOL] indicator?

Thanks to @filbranden's answer I added the following line to my .vimrc file:

au BufWritePost * if !&endofline && &fixeol && !&binary | set endofline |  endif

The endofline option will now be updated if a new line character was added to a file's end. However, this is only half the way: If I remove a trailing new line character from a file, the endofline option will stay true.

FYI: I need this to edit some binary files (:set binary | %!xxd / %!xxd -r) without corruption through accidental added/removed trailing new line characters.

  • Welcome to Vi and Vim! – filbranden May 17 at 17:23
  • Your follow up is more like a separate question, since it's really about the behavior of the binary/eol in the :%! operation... @D.BenKnoble you wrote vim-hex (which you @dirdi might want to try!), can you pitch in on adding/removing newlines when xxd'ing back and forth? – filbranden May 17 at 19:23
  • 1
    @filbranden you are right: it boils down to the :%! operation. Vim adds a trailing new line char to the stream if the endofline option is set. But the endofline option is not in sync with the buffer's content. AFAICS vim-hex is also affected by this problem. – dirdi May 17 at 20:56
  • 1
    Just saw this; I’ll have to do some digging (I havent had to touch vim-hex’s code for a while). If there is a bug about adding trailing newlines, I’d love to know and fix it. – D. Ben Knoble May 17 at 21:08
3

This behavior is intentional, to keep track of the original [noeol] status of the file when it was first read.

Note that you can control whether to keep the original [noeol] status of a file when writing it by setting 'nofixeol':

When writing a file and this option is on, <EOL> at the end of file will be restored if missing. Turn this option off if you want to preserve the situation from the original file. See the 'endofline' option.

(You can also achieve the same effect of preserving the [noeol] status by setting the 'binary' option, which you can do with the -b command-line option or using :e ++bin.)

Vim will only set noeol when reading files that don't include a final <EOL>. See :help 'eol':

[...] This option is automatically set or reset when starting to edit a new file, depending on whether file has an <EOL> for the last line in the file. Normally you don't have to set or reset this option. [...] it is used to remember the presence of a <EOL> for the last line in the file, so that when you write the file the situation from the original file can be kept. But you can change it if you want to.

So I understand the rationale here is that it will keep remembering the original state of this setting, if later on you decide you want to preserve it, with set nofixeol, the fact that you may have written the file doesn't really affect the original [noeol] status of the file, which is still remembered.

And since 'fixeol' is the default, the fact that the original [noeol] status is remembered doesn't really matter much, since unless you changed this setting, Vim will end up fixing the file when writing it.

If you really want to reset the [noeol] status of the file after writing it, one way to do it is by reading it back using a bare :e, which will simply re-read the file being edited. As documented, this will reset the [noeol] status of the file, which should now be fixed.

(Another alternative is for you to check whether Vim will have fixed it, by checking that 'binary' is disabled and 'fixeol' is enabled, and then update 'eol' accordingly. This reimplements some internal Vim logic, but this logic should be fairly stable, so it's not that an unreasonable thing to do.)

| improve this answer | |
  • 1
    Thanks to your answer, I was able to solve half of my problem ;D I updated my question and maybe you can extend/update your answer accordingly. – dirdi May 17 at 18:48

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.