Skip to content
This repository has been archived by the owner on Mar 3, 2023. It is now read-only.

Suppress display of end-of-file newlines as blank lines #7787

Closed
mainameiz opened this issue Jul 8, 2015 · 59 comments
Closed

Suppress display of end-of-file newlines as blank lines #7787

mainameiz opened this issue Jul 8, 2015 · 59 comments

Comments

@mainameiz
Copy link

Atom by default inserts a new line (a line break actually) at the end of file (and it's cool), but it also shows this newline as an empty line at the end of file, but it's prefereably don't do this. How can I fix this? Thank you very much.

@oBlissing
Copy link

Look here: #4741

@mainameiz
Copy link
Author

It's not what I want. I want a line break at the end of file but I don't want to show it as an empty line. There is a difference between line break and empty line

@mainameiz
Copy link
Author

https://robots.thoughtbot.com/no-newline-at-end-of-file

"So, it turns out that, according to POSIX, every text file (including Ruby and JavaScript source files) should end with a \n, or “newline” (not “a new line”) character. This acts as the eol, or the “end of line” character. It is a line “terminator”."

@biffen
Copy link

biffen commented Jul 9, 2015

There is a difference between line break and empty line

How do you mean? Could you show the hexdumps of a file that ends in a newline and one that ends with an empty line (encoded in, say, ASCII, and containing, say, foo). In my mind they're the same:

00000000  66 6f 6f 0a                                       |foo.|
00000004

@mainameiz
Copy link
Author

@biffen Its not about how it represented in hex-dumps (its the same), Its about how an editor displays a newline, It should not show empty line because there is "\n" character at hte end of file

@biffen
Copy link

biffen commented Jul 9, 2015

@mainameiz Then what is the difference between an empty line and a newline that isn't followed by anything?

@mnquintana
Copy link
Contributor

I can see why you might want to hide it, but then how would you know that any file indeed is ending with a \n character as it should? Sure, if you saved a file with Atom with the default settings, if you "knew" beforehand you could assume that the newline was being added on save, but new users wouldn't have the prior knowledge to make this assumption. Instead they'd assume Atom was making no changes on save until taking a look at their git diff, which would make this feature all the more confusing.

I'd be possibly 👍 for a package that does this, but very 👎 about changing this in core.

@mainameiz
Copy link
Author

@mnquintana It must be an option of course.

@mainameiz
Copy link
Author

@biffen

> hexdump -c test.txt                                                                                     (master⚡)
0000000   1  \n                                                        
0000002

vim

> hexdump -c test.txt                                                                                     (master⚡)
0000000   1  \n  \n                                                    
0000003

vim

@mainameiz
Copy link
Author

I have changed my opinion it must be default behaviour :-) It is unix agreement and I don't see any reasons why somebody might want not to insert new line at the end of file.

@izuzak
Copy link
Contributor

izuzak commented Jul 10, 2015

@mainameiz Just to make sure I understand your suggestion, can you clarify how these two files would be displayed and what the difference would be:

$ hexdump -c test1.txt
0000000   c  \n                                                        
0000002

$ hexdump -c test2.txt
0000000   c                                                            
0000001

@mainameiz
Copy link
Author

It will look like this vim . Both. Difference is how an editor represents "\n" character. 1) as a line terminator 2) as a "new empty line". My vim use " \n" as a line terminator (see screenshot above). But atom will show me two lines (c + an empty line) in your first case :-(

@exogen
Copy link

exogen commented Jul 14, 2015

As @mainameiz suggests, there is some precedence for this. In Vim, test\n will show one line, and not show a numbered line 2. If you do type test and press Enter to create a second line, there are actually two newlines (test\n\n). In Python, "test\n".splitlines() will return ['test'] (one line), not ['test', ''], etc.

It may seem like a small thing, but it has actually been driving me nuts since using Atom. I keep thinking "why is there an extra blank line at the end of this file?!" when there is no "extra" line – just a newline terminating the actual last line.

@mnquintana mnquintana changed the title How to make atom not to show line breaks as new lines. Suppress display of end-of-file newlines as blank lines Sep 9, 2015
@dowdell
Copy link

dowdell commented Sep 9, 2015

+1

@dylanwinn
Copy link

dylanwinn commented Sep 14, 2015

I would like to add that I appreciate that atom makes sure that there is a newline at the end of the file by default, a lot of text editors (nano) miss this kind of basic stuff. However, that newline should definitely not be rendered as an additional black line. By definition, a newline signifies the end of a line, not the beginning. I understand that the naming in confusing but all other Unix utilities work like this. If you open up a file in vim or emacs or run it through wc -l it will report one less line than atom shows.

@mnquintana
Copy link
Contributor

One idea for this - instead of displaying a blank line, do what GitHub does and display nothing. If there is no trailing newline, then display this icon at the end of the last line, like GitHub does in diffs.

@glen-84
Copy link

glen-84 commented Dec 4, 2015

This is the main reason why I've been resisting enabling the "ensure single trailing newline" setting – the fact that there is a line number but no line content really bothers me.

To make it crystal clear:

Currently:

1. Line 1\n
2. \n
3. Line 3\n
4.

What it should be:

1. Line 1\n
2. \n
3. Line 3\n

@dowdell
Copy link

dowdell commented Dec 4, 2015

"ensure single trailing newline" enabled or not, atom will still show a 4th empty line if your 3rd line ends with a newline. The setting is helpful in ensuring it is not forgotten

@glen-84
Copy link

glen-84 commented Dec 4, 2015

@triplesek I'm not sure what you're referring to. The setting is fine – the line numbering is not.

@dowdell
Copy link

dowdell commented Dec 4, 2015

@glen-84 What I'm saying is that this issue occurs whether or not you choose to enable the "ensure single trailing newline" setting. I don't see why this would cause you to resist enabling it, since presumably you'd want all of your lines to end with a \n anyway.

@glen-84
Copy link

glen-84 commented Dec 4, 2015

@triplesek I couldn't get used to the idea of what looks like a blank line at the end of files, so I disabled that setting. However, I came to the realization that this is the correct behaviour, but the editor is incorrectly numbering the final line.

@spinningarrow
Copy link

I think GitHub does this the best - for files that don't end in a \n, there's a little icon at the end of the last line. Files that do end with a \n don't show anything special (or any extra lines). If GitHub followed Atom's behaviour, all the files would show an extra numbered line in the end, which is confusing too.

@Pacoup
Copy link

Pacoup commented Sep 22, 2016

Ignoring teletypewriter history, as far as I know, CP/M's filesystem could not record the size of a file, so you had to specify an end of file delimiter, normally Control-Z; i.e. 1A hex. This would give text files like this:

line[CR+LF]
line[CR+LF]
line[Control+Z]

But I believe this would have also been completely valid:

line[CR+LF]
line[CR+LF]
line[CR+LF][Control+Z]

Conversely, Unix filesystems did record file sizes so you didn't have to end files with an end of file delimiter. Instead, the end of record delimiter was used to end every line. Furthermore, Unix chose to omit the CR delimiter (purportedly, this would have been to save some memory). So text files looked like this:

line[LF]
line[LF]
line[LF]

Apple did the same but chose to omit LF instead, so files looked like this:

line[CR]
line[CR]
line[CR]

If you think about it, then, in CP/M, CR+LF meant new line, but in Unix, LF meant end of line. In this respect, it would have been correct for early display editors in Unix to display the above examples as three lines, but it would have also been correct for CP/M to display the above examples as four lines.

C, which became popular in the 70s/80s, was built for Unix, so it followed the mandatory delimiter practice, and I believe most if not all early compilers wouldn't work without the last line of code ending with an end of record delimiter. So you had CP/M derivatives which would show a new line after every end of record delimiter, and C, which would require an end of record delimiter for the last line of code, and every CP/M derivative developer would have gotten into the habit of putting an extra line at the end of their source code to please C compilers.

CP/M derivatives became incredibly popular thanks to IBM and Microsoft's success, so, that's a lot of developers putting new lines at the end of their code.

This seems to have been so pervasive that every single text editor and IDE except for Vim currently prints an extra line after LF. Yes, even Emacs, although it hides the number of the extra line in linum-mode. Smart.

So neither is right, historically-speaking, but on Unix, LF does mean end of a line. The POSIX standard defines a line as:

A sequence of zero or more non-<newline> characters plus a terminating <newline> character.

In other words, a sequence of zero or more non-<newline> characters without a terminating <newline> character is not a line, and text editors have no business showing a new line there on Unix-like systems.

But then there's the issue of what to do with CR+LF and Windows developers, and do you really want all those developers to start adding two LF at the end of every file because they think the new line is missing. Sigh…

So, maybe just an option to remove the extra visual line would be nice.

@ghost
Copy link

ghost commented Sep 28, 2017

@glen-84 I am suggesting this purely in the presence of Linux line breaks. So yes, I'm assuming Linux (where no EOF would be super unique). macOS and Windows use different byte characters as line breaks anyway, don't they?

@glen-84
Copy link

glen-84 commented Sep 28, 2017

macOS and Windows use different byte characters as line breaks anyway, don't they?

MacOS uses \n (same as Linux ... they used to use \r). Windows uses \r\n.

@ghost
Copy link

ghost commented Sep 28, 2017

Will \n at the end of a file show up as a visible trailing empty line on Mac OS X in any native editor? Might be worth testing with hexdump (to check the actual trailing \n characters in the binary contents of hte file).

I hope it behaves similar to Linux, but if it doesn't this might make this issue a lot more complicated.

@ghost
Copy link

ghost commented Sep 28, 2017

To sum it up:

  1. Linux: single trailing \n should not lead to a visible trailing empty line
  2. Windows: single trailing \r\n should lead to a visible trailing empty line (check this in Notepad.exe on current Windows 10 for reference)
  3. macOS: ??

@glen-84
Copy link

glen-84 commented Sep 28, 2017

Will \n at the end of a file show up as a visible new line on Mac OS X?

I'm almost certain that you'll see the same behaviour across all platforms.

@ghost
Copy link

ghost commented Sep 28, 2017

@glen-84 it certainly differs from Windows, where a single trailing \r\n actually leads to a visible trailing empty line (shown in Microsoft's own Notepad.exe):

notepad

.. while a trailing \n on most older common Linux editors doesn't. So it doesn't seem to be fully platform-consistent..

@glen-84
Copy link

glen-84 commented Sep 28, 2017

@maxbrunsfeld
Copy link
Contributor

maxbrunsfeld commented Sep 28, 2017

Yeah, AFAICT there's really nothing platform specific about this issue. This is purely a visual concern about line numbers appearing (or not appearing) in the gutter. We don't have a mandate to mimic any particular editor on Windows, Linux or macOS. We just need to decide on a visual presentation that makes sense from first principles. I am on board with changing our current rendering, but I'm not really on board with doing it differently on different platforms because there is really no need for that.

@ghost
Copy link

ghost commented Sep 28, 2017

Yea I think Atom should follow the canonical \r\n interpretation of Microsoft Windows when running on Linux as well.

However, this leads us back to the issue that in this case, Windows line break files with active atom/whitespace package will be saved with what shows up in all Windows editors (and Atom on all platforms) as a trailing empty line, while Linux line break files with active atom/whitespace package would be saved with what is no visible trailing empty line in most Linux editors. This can be considered intended, but I think this visual inconsistency is bad.

@glen-84
Copy link

glen-84 commented Sep 28, 2017

@maxbrunsfeld,

But if Windows doesn't follow POSIX (AFAIK), then Atom should show:

1. Line 1\r\n
2.

In Windows, and:

1. Line 1\n

On Linux/MacOSX.

... or am I missing something?

@ghost
Copy link

ghost commented Sep 28, 2017

Edit: sorry, mixed up the ticket tabs and this is a bit misplaced here

@maxbrunsfeld
Copy link
Contributor

maxbrunsfeld commented Sep 28, 2017

This issue is orthogonal to whether you're using \r\n or \n as your line ending.

Currently, if you open a file containing the text hello\n, we show this:

1| hello
2|

And if the file uses windows line endings (hello\r\n), we show the exact same thing. It doesn't matter at all what platform you're using. Our rendering does not depend on the platform.

The issue is that people find it confusing that we show the line number 2. I agree; I think we should simply hide the 2.

@glen-84
Copy link

glen-84 commented Sep 28, 2017

@maxbrunsfeld,

It's not that simple.

  1. Not showing the numbered line is the correct behaviour when using \n only, AFAIK. (see other Windows editors that will show the empty line [VS, etc.])
  2. Just hiding the line number for \n could add more confusion, and lead to users (used to seeing a blank line) adding another and ending up with \n\n. There should perhaps be a visual indication that an EOF newline is present (a middle dot, different bg colour, etc.)

@maxbrunsfeld
Copy link
Contributor

maxbrunsfeld commented Sep 28, 2017

  1. We don't need to do the same thing as windows editors just because you're editing a file with CRLF line endings. That just happens to be the UX of particular windows editor(s). We can have a different UX. Notepad is not the source of truth for how CRLF line endings should be handled. It's just one random Windows program.

  2. There is going to be some confusion no matter what we do. Atom is different from vim on purpose - trailing newlines are not a baked-in assumption, they are just the default behavior, provided via a package. There is no way for us to completely eliminate confusion for all users, but it seems like a fair number of people are getting confused by the fact that we show that final line number.

@ghost
Copy link

ghost commented Sep 28, 2017

I think what Vim etc should do for Windows line breaks derails us a bit. Nevertheless for what it's worth, I am quite sure most Windows editors behave like Notepad and Notepad is about the closest source of truth to get (since it's written by Microsoft after all). But I guess nobody disputes the current \r\n handling of Atom anyway, which I suggest should remain unchanged including for when it runs on Linux and continue to show a trailing empty line for a single trailing \r\n.

@glen-84
Copy link

glen-84 commented Sep 28, 2017

  1. If it's different to almost every other Windows editor, that would quite likely confuse users.
  2. Maybe some visual indication like this?

atom-invis-line

@ghost
Copy link

ghost commented Sep 28, 2017

What is the corresponding hex bytes for each example?

@maxbrunsfeld
Copy link
Contributor

@Jonast As before, we're talking about a file with a single trailing newline (so Line 1\n, or Line 1\r\n, it doesn't matter).

I believe @glen-84 is showing 3 different possible renderings that we could adopt for this file.

@maxbrunsfeld
Copy link
Contributor

Personally, I'm in favor of just leaving it blank, since the symbol is already used for line continuations in the presence of soft wraps.

@ghost
Copy link

ghost commented Sep 28, 2017

Well I think none of those renderings should be used for Line 1\r\n since that should show an actual trailing empty line 2.

As for Line 1\n, I think the best choice is also none of those but simply showing only one line as other Linux editors.. (and an indicator for the different text file Line 1 that indicates the missing\n, with the indicator either present when Atom runs on Linux or when other \n characters have been used previously for line breaks in the opened file - similar to the GitHub web render UI)

@glen-84
Copy link

glen-84 commented Sep 28, 2017

What is the corresponding hex bytes for each example?

\n is decimal 10 or hex a
\r is decimal 13 or hex d

@perennialmind
Copy link

I am with @glen-84: \r\n signifies a line separator and a bare \n is a line terminator. You basically have two distinct file formats for multiline text: the semantics are tied to the data, not the platform. Save a two-line file with Windows conventions, and you should get exactly one line break sequence (1\r\n2). Save the same file with Unix conventions, and you should get exactly two instances (1\n2\n).

The "ensure single trailing newline" is only relevant for \r\n encoded files, and should display as a third, blank line. The option is still valuable, but mostly for working with software of a Unix background like git.

Text files with bare \n breaks without a final \n are anomalous and may be malformed.

@ghost
Copy link

ghost commented Dec 7, 2017

@perennialmind that's pretty much what I keep suggesting, yes. The trailing \n missing is the special case and should be the only one that shows up with some sort of special marker, if at all. And in overall, it should IMHO work exactly as you described.

The "ensure single trailing newline" is only relevant for \r\n encoded files, and should display as a third, blank line. The option is still valuable, but mostly for working with software of a Unix background like git.

Not sure I agree with this one, because if it was implemented exactly like that it'd mean the end result shows up differently depending on whether you save the file with windows line breaks or unix line breaks.

However, I also think the behavior of the whitespace package should probably kept and discussed entirely separate and the more important thing is to fix the line rendering in the Atom core first, and wonder about the package later. (instead of catering the line rendering of Atom the other way around to whatever the whitespace package does).

@perennialmind
Copy link

@Jonast, I think I see where you're coming from. From the "file format" perspective, the save options should not affect the line/buffer display. Furthermore, having just discovered .editorconfig, I see that there is another dimension of compatibility to worry about. Fun!

Would it be reasonable to make the line separator/terminator interpretation a feature of the core editor, normally determined based on detected line-break sequence? That should do the Right Thing™ 95% of the time and make the subtleties more explicit. Packages such as whitespace could provide a manual override for the remaining 5%. This might also make the implementation for the existing editorconfig package a bit cleaner.

As a user, I would expect all numbered lines to be "real". If Atom tells me a LF-terminated file has five lines, I expect Atom, vim, and wc -l to agree on that count. If Atom saves that same file with CRLF-separators, I expect Visual Studio to show me lines numbered 1 through 5.

When saving a two-line file with the first line containing "L1" and the second blank:

default as terminators as separators
CRLF L1\r\n L1\r\n\r\n L1\r\n
LF L1\n\n L1\n\n L1\n

When reading a file, counted/numbered lines:

default as terminators as separators
L1\r\n 2 1 2
L1\r\n\r\n 3 2 3
L1\r\nL2 2 2* 2
L1\n\n 2 2 3
L1\n 1 1 2
L1 1 1* 1
L1\nL2 2* 2* 2
L1\nL2\r\n 2 or 3 2 3

Cases with a "*" imply a detectable deviation from expectations and, presumably, an applied correction. With the rules above, saving such files when otherwise unmodified, would change the contents on disk. That might merit a visual indicator of some kind. Either that or expose the terminator/separator option per-file, like vim does. One possibility would be to augment the line-ending indicator/selector widget with two more options for the special cases, makig it CRLF, LF, CRLF-term, and LF-sep.

I don't think that the mixed linebreak case has a correct heuristic, but on the flip side, there's no wrong answer either.

P.S. LF line separators might never make sense. You see CRLF terminators in the real world: email, http, and plenty of other RFCs call for end-of-line markers as CRLF. I maintain that the existing "ensure single trailing newline" option ought only apply to CRLF files, but as @Jonast says, that's a package concern.

P.P.S. Sorry for the insufferable detail. These are the details that drive me nuts.

@b1f6c1c4
Copy link

As a fundamentalist who thinks \n marks the termination of one single line, I wrote an atom package https://atom.io/packages/no-evil-eol-newline that gives a presentational fix for this issue. Hope that helps.

Everything here is about presentation. File content is not mutated by this package.

image

@ghost
Copy link

ghost commented Mar 18, 2018

@b1f6c1c4 yea, that's exactly how core Atom should behave (except maybe a nice icon instead of just red coloring would be nice for the missing \n case - but I understand your main priority was probably to get this working in the first place).

@lee-dohm
Copy link
Contributor

Since @b1f6c1c4 was kind enough to write a package to handle this and since this is pretty low on the maintainer team's priority list, I'm going to close this for now. If anyone is interested in this functionality, please check out @b1f6c1c4's package no-evil-eol-newline 👍

@lock
Copy link

lock bot commented Sep 14, 2018

This issue has been automatically locked since there has not been any recent activity after it was closed. If you can still reproduce this issue in Safe Mode then please open a new issue and fill out the entire issue template to ensure that we have enough information to address your issue. Thanks!

@lock lock bot locked as resolved and limited conversation to collaborators Sep 14, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests