editorconfig / editorconfig-vim

EditorConfig plugin for Vim
http://editorconfig.org
Other
3.14k stars 138 forks source link

insert_final_newline not respected #136

Open thet opened 4 years ago

thet commented 4 years ago

When editing a file with the following .editorconfig loaded:

[*]
indent_style = space
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
charset = utf-8

no final newline is inserted.

cxw42 commented 4 years ago

Thanks for reporting! Would you please tell us the steps you took and how you discovered this? For example, empty files should stay empty. Could you share the file you were editing, as an attachment? Much appreciated!

keithbowes commented 4 years ago

:echo &eol should give you 1. You won't actually see a new line.

oiwn commented 4 years ago

hm, just trying to figure out why no newline inserted.

similar config, neovim with editorconfig-vim.

cxw42 commented 4 years ago

@istinspring Would you please tell us the steps you took that led you to discover the issue? Please attach any files you used (but no private information, please). Thanks!

oiwn commented 4 years ago
# EditorConfig helps developers define and maintain consistent
# coding styles between different editors and IDEs
# http://editorconfig.org

root = true

[*]

# Change these settings to your own preference
indent_style = space
indent_size = 2

# We recommend you to keep these unchanged
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[*.py]
indent_size = 4

[*.md]
trim_trailing_whitespace = false

[*.html]
indent_size = 2

[*.json]
indent_size = 2

[Makefile]
indent_style = tab
indent_size = 2

config. when you want to copy all lines in file you usually go ggvG in vim, but this last G do not cover last line.

oiwn commented 4 years ago

hm actually there is issue already https://github.com/editorconfig/editorconfig-vim/issues/74

so i used hexdump to look what's actually in file

00001d0   e   t   i   m   e   ]       =       N   o   n   e  \n
00001de

and looks like there is new line already? am i right?

k-takata commented 4 years ago

Vim assumes that every text line ends with a newline. So, even if you don't see any empty line at the end of the file on Vim, the final newline will be added by default. insert_final_newline = true is the default behavior of Vim.

If you set insert_final_newline = false, this plugin may remove the final newline by doing setl nofixendofline. (Actually, the final newline will be removed if the eol option is unset (setl noeol).)

alexdilley commented 3 years ago

If you set insert_final_newline = false, this plugin may remove the final newline by doing setl nofixendofline. (Actually, the final newline will be removed if the eol option is unset (setl noeol).)

Yes, setl nofixendofline only honours the EOL of an existing file (but will add an <EOL> for a new file). setl noeol therefore feels more appropriate for a insert_final_newline = false config as it should be honoured in all cases, suggesting this line is wrong?

cxw42 commented 3 years ago

The specification is clear that false means "ensure [the file being saved] doesn’t" end with a newline.

From the Vim docs, it looks like we need to set both noeol and nofixeol to actually remove the newline. PR welcome!

Diomendius commented 3 years ago

The docs are a little cryptic, but the purpose of both endofline and fixendofline seems clear to me.

endofline indicates whether the file has a trailing <EOL>, as Vim doesn't track this as part of its buffer representation. As stated in the docs, this is set automatically on :edit. Changing this setting effectively adds or removes the trailing <EOL> from the buffer.

fixendofline indicates whether Vim should add a trailing <EOL> when saving a buffer that doesn't already have one. This is not set automatically.

Therefore:

vim-airline displays [!EOL] by default in the status line when endofline is unset. Changing this setting immediately affects the display of this indicator. Considering in the insert_final_newline = false case it's necessary to set noendofline, which will prevent the display of [!EOL] by vim-airline (and probably prevent the user from knowing whether the file originally had a trailing <EOL> at all without circumventing this plugin in some way), there is an argument that endofline should be set when insert_final_newline = true, for consistency. Otherwise, when insert_final_newline = false, Vim pretends the file didn't have a trailing <EOL> even if it did, but when insert_final_newline = true, Vim preserves this information, even though writing to the file will add a trailing <EOL> if not present.

The obnoxious kludgy way to avoid this quirk would be to hook an autocommand to BufWrite to set/unset endofline based on insert_final_newline.

Marlliton commented 2 years ago

in my case I am trying not to insert a newline but the newline is always inserted at the end of the file. root = true

root = true
[*]
indent_style = space
indent_size = 4
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
[*.{ts,js}]
insert_final_newline = false

the code below is the same, the line is always inserted:

root = true
[*]
indent_style = space
indent_size = 4
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true

insert_final_newline = false
TysonAndre commented 2 years ago

When insert_final_newline = true, setl fixendofline should be run. setl endofline could also be run, but this would have no effect unless the user manually changes fixendofline.

EDIT: I had enabled set binary years ago as a workaround for vim versions too old to have fixendofline, and didn't realize it. Sorry, the current handling makes sense

When I use :r testname.out to read the lines of a file (where testname.out has no trailing newline) into the end of a file or replace the end of a file (e.g. testname.phpt), the resulting file has no newline when saving without setl endofline.

So there are use cases for adding endofline. What I have this overridden to locally is:

The relevant section of the vim help for 'endofline'

'endofline' 'eol' boolean (default on) local to buffer

When writing a file and this option is off and the 'binary' option is on, or 'fixeol' option is off, no <EOL> will be written for the last line in the file. 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. When 'binary' is off and 'fixeol' is on the value is not used when writing the file. When 'binary' is on or 'fixeol' is off 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.

cxw42 commented 2 years ago

While reviewing this, I realized the specification is at odds with the behaviour being implemented in this PR. I have opened https://github.com/editorconfig/editorconfig/issues/475 to clarify the specification.