What's the point in adding a new line to the end of a file?

  • Some compilers (especially C or C++ ones) give you warnings about:

    No new line at end of file
    

    I thought this would be a C-programmers-only problem, but github displays a message in the commit view:

    \ No newline at end of file
    

    for a PHP file.

    I understand the preprocessor thing explained in this thread, but what has this to do with PHP? Is it the same include() thing or is it related to the \r\n vs \n topic?

    What is the point in having a new line at the end of a file?

    To piss people off.

    If you `cat` the file, the next prompt will be appended to the final "line" if it does not end with a newline.

  • It's not about adding an extra newline at the end of a file, it's about not removing the newline that should be there.

    A text file, under unix, consists of a series of lines, each of which ends with a newline character (\n). A file that is not empty and does not end with a newline is therefore not a text file.

    Utilities that are supposed to operate on text files may not cope well with files that don't end with a newline; historical Unix utilities might ignore the text after the last newline, for example. GNU utilities have a policy of behaving decently with non-text files, and so do most other modern utilities, but you may still encounter odd behavior with files that are missing a final newline¹.

    With GNU diff, if one of the files being compared ends with a newline but not the other, it is careful to note that fact. Since diff is line-oriented, it can't indicate this by storing a newline for one of the files but not for the others — the newlines are necessary to indicate where each line in the diff file starts and ends. So diff uses this special text \ No newline at end of file to differentiate a file that didn't end in a newline from a file that did.

    By the way, in a C context, a source file similarly consists of a series of lines. More precisely, a translation unit is viewed in an implementation-defined as a series of lines, each of which must end with a newline character (n1256 §5.1.1.1). On unix systems, the mapping is straightforward. On DOS and Windows, each CR LF sequence (\r\n) is mapped to a newline (\n; this is what always happens when reading a file opened as text on these OSes). There are a few OSes out there which don't have a newline character, but instead have fixed- or variable-sized records; on these systems, the mapping from files to C source introduces a \n at the end of each record. While this isn't directly relevant to unix, it does mean that if you copy a C source file that's missing its final newline to a system with record-based text files, then copy it back, you'll either end up with the incomplete last line truncated in the initial conversion, or an extra newline tacked onto it during the reverse conversion.

    ¹ Example: the output of GNU sort always ends with a newline. So if the file foo is missing its final newline, you'll find that sort foo | wc -c reports one more character than cat foo | wc -c.

    Concerning "... series of lines, each of which must end with a newline character (n1256 §5.1.1.1)" --> In re-viewing a the more recent C11dr N1570, did not find support for that other than maybe: "A source file that is not empty shall end in a new-line character, which shall not be immediately preceded by a backslash character before any such splicing takes place." §5.1.1.2 2, but that seems to be restricted to splicing specifications.

    @chux That sentence is present in n1256 too. The last line must end with a newline character. Lines that are not the last line must obviously also end with a newline character to indicate that that line ends and the next line begins. Thus every line must end with a newline character.

    Hmmm, To me, that line ""A source file ... splicing takes place." could be limited to how splicing considerations and not files in general. Yet I see how one could view otherwise. Perhaps I'll look for a post that focuses on that.

    >"So diff uses this special text \ No newline at end of file to differentiate a file that didn't end in a newline from a file that did." Git shows this text not only when it compares files. But even when new file added to git. So this argument is not valid, I suppose.

    > "Utilities that are supposed to operate on text files may not cope well with files that don't end with a newline" I don't think that it's business of git to care about such low level problems like missing \n because of POSIX requirements. I think that if git shows this message, reason should be in _source control_ problems.

    In PHP what if you have closing tag ?>\n at the end of php file \n would lead to additional unnecessary new line in server response.

    @ViktorKruglikov I don't think PHP cares whether its source file ends with a newline. But PHP is typically used this way to generate HTML, and a newline at the end of an HTML is not a problem.

    @Gilles > "and a newline at the end of an HTML is not a problem" But php may generate not only html, but any type of file: pdf, csv, or any custom filetype. Also in php if you work with http headers, and you've sent any html content (including \n) to responce before you handled http headers, you get errors. I still think that newline at the end of file is not git's business. Or there is some reason that we're missing.

    @ViktorKruglikov If you're generating a binary file with embedded PHP, then your PHP source file is not a text file. It's unusual for source code not to be in text files. Git is primarily designed to handle text files, so its user interface makes text files the default and lets you know if what you have is not a text file.

    Why not just update the archaic tools instead so they don't break if there's a missing new line...

    @ViktorKruglikov: This is why there is the ages old PSR-1 rule to *not* terminate any files with the closing `?>` "*tag*" if that file is not in HTML (output) context (just leave it out, PHP is fine with that). For HTML context +1 what Gilles wrote, HTML also has whitespace normalization and this all should be compatible w/ the HTTP protocol as well, but that just as a note in the margin.

License under CC-BY-SA with attribution


Content dated before 6/26/2020 9:53 AM