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 TextMate users, you can install the Avian Missing
TM_STRIP_WHITESPACE_ON_SAVE = trueto your
- For Sublime users, set the
- For RubyMine, set “Ensure line feed at file end on Save” under “Editor.”
If this satisfied your curiosity, you might also enjoy: