Have you ever seen “No newline at end of file” in your git diffs? Us, too.
~/.dotfiles% git diff diff --git a/vimrc b/vimrc index 7e31913..a8b5f95 100644 --- a/vimrc +++ b/vimrc @@ -2,4 +2,4 @@ let configs = split(glob("~/.vim/configs/*"), "\n") for filename in configs execute 'source ' filename -endfor +endfor \ No newline at end of file
Why does this happen and what does it mean?
Here I have made a text file and, by definition, a non-text file:
~% echo foo > text-file ~% od -c text-file 0000000 f o o \n 0000004 ~% wc -l text-file 1 text-file ~% echo -n foo > binary-file ~% od -c binary-file 0000000 f o o 0000003 ~% wc -l binary-file 0 binary-file
If you open each file in vim, they will display similarly. The intuition behind
what vim is doing is “separate each line with a line break”, which is different
from “display each
\n as a line break”.
binary-file will cause vim to display
[noeol] in its status
line (with the default status line).
This comes from an old C decision that has been passed down through Unix history:
A source file that is not empty shall end in a new-line character, which shall not be immediately preceded by a backslash character.
Since this is a “shall” clause, we must emit a diagnostic message for a violation of this rule.
So, it turns out that, according to POSIX, every text file (including
\n, or “newline” (not “a
new line”) character. This acts as the
eol, or the “end of line”
character. It is a line “terminator”.
You can make sure you follow this rule easily:
- For Vim users, you’re all set out of the box! Just don’t change your
- For Emacs users, add
(setq require-final-newline t)to your
- For Android Studio, RubyMine, PyCharm, and other IntelliJ, set “Ensure line feed at file end on Save” under “Editor.”
- For Atom, you’re also all set out of the box. Keep that via the Whitespace plugin.
- For VS Code, set
- For Sublime, set the
- For TextMate, you can install the Avian Missing
TM_STRIP_WHITESPACE_ON_SAVE = trueto your
If this satisfied your curiosity, you might also enjoy: