0
0
mirror of https://github.com/vim/vim.git synced 2025-09-30 04:44:14 -04:00

patch 9.0.0826: if 'endofline' is set CTRL-Z may be written in a wrong place

Problem:    If 'endofline' is set the CTRL-Z may be written in the wrong
            place.
Solution:   Write CTRL-Z at the end of the file.  Update the help to explain
            the possibilities better. (Ken Takata, closes #11486)
This commit is contained in:
K.Takata
2022-11-01 20:36:19 +00:00
committed by Bram Moolenaar
parent 8e0ccb6bc2
commit 3af982196b
6 changed files with 136 additions and 19 deletions

View File

@@ -578,6 +578,43 @@ single <NL> characters are unexpectedly replaced with <CR><NL>.
You can encrypt files that are written by setting the 'key' option. This You can encrypt files that are written by setting the 'key' option. This
provides some security against others reading your files. |encryption| provides some security against others reading your files. |encryption|
END OF LINE AND END OF FILE *eol-and-eof*
Vim has several options to control the file format:
'fileformat' the <EOL> style: Unix, DOS, Mac
'endofline' whether the last line ends with a <EOL>
'endooffile' whether the file ends with a CTRL-Z
'fixendofline' whether to fix eol and eof
The first three values are normally detected automatically when reading the
file and are used when writing the text to a file. While editing the buffer
it looks like every line has a line ending and the CTRL-Z isn't there (an
exception is when 'binary' is set, it works differently then).
The 'fixendofline' option can be used to choose what to write. You can also
change the option values to write the file differently than how it was read.
Here are some examples how to use them.
If you want files in Unix format (every line NL terminated): >
setl ff=unix fixeol
You should probably do this on any Unix-like system. Also modern MS-Windows
systems tend to work well with this. It is recommended to always use this
format for Vim scripts.
If you want to use an old MS-DOS file in a modern environment, fixing line
endings and dropping CTRL-Z, but keeping the <CR><NL> style <EOL>: >
setl ff=dos fixeol
This is useful for many MS-Windows programs, they regularly expect the
<CR><NL> line endings.
If you want to drop the final <EOL> and add a final CTRL-Z (e.g. for an old
system like CP/M): >
setl ff=dos nofixeol noeol eof
If you want to preserve the fileformat exactly as-is, including any final
<EOL> and final CTRL-Z: >
setl nofixeol
============================================================================== ==============================================================================
3. The argument list *argument-list* *arglist* 3. The argument list *argument-list* *arglist*

View File

@@ -3056,6 +3056,7 @@ A jump table for the options with a short description can be found at |Q_op|.
When writing a file and this option is off and the 'binary' option When writing a file and this option is off and the 'binary' option
is on, or 'fixeol' option is off, no CTRL-Z will be written at the is on, or 'fixeol' option is off, no CTRL-Z will be written at the
end of the file. end of the file.
See |eol-and-eof| for example settings.
*'endofline'* *'eol'* *'noendofline'* *'noeol'* *'endofline'* *'eol'* *'noendofline'* *'noeol'*
'endofline' 'eol' boolean (default on) 'endofline' 'eol' boolean (default on)
@@ -3071,6 +3072,7 @@ A jump table for the options with a short description can be found at |Q_op|.
to remember the presence of a <EOL> for the last line in the file, so 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 that when you write the file the situation from the original file can
be kept. But you can change it if you want to. be kept. But you can change it if you want to.
See |eol-and-eof| for example settings.
*'equalalways'* *'ea'* *'noequalalways'* *'noea'* *'equalalways'* *'ea'* *'noequalalways'* *'noea'*
'equalalways' 'ea' boolean (default on) 'equalalways' 'ea' boolean (default on)
@@ -3466,6 +3468,7 @@ A jump table for the options with a short description can be found at |Q_op|.
When the 'binary' option is set the value of this option doesn't When the 'binary' option is set the value of this option doesn't
matter. matter.
See the 'endofline' option. See the 'endofline' option.
See |eol-and-eof| for example settings.
*'fkmap'* *'fk'* *'nofkmap'* *'nofk'* *'fkmap'* *'fk'* *'nofkmap'* *'nofk'*
'fkmap' 'fk' boolean (default off) 'fkmap' 'fk' boolean (default off)

View File

@@ -2050,10 +2050,6 @@ restore_backup:
len = 0; len = 0;
write_info.bw_start_lnum = lnum; write_info.bw_start_lnum = lnum;
} }
if (!buf->b_p_fixeol && buf->b_p_eof)
// write trailing CTRL-Z
(void)write_eintr(write_info.bw_fd, "\x1a", 1);
// write failed or last line has no EOL: stop here // write failed or last line has no EOL: stop here
if (end == 0 if (end == 0
|| (lnum == end || (lnum == end
@@ -2158,6 +2154,13 @@ restore_backup:
nchars += len; nchars += len;
} }
if (!buf->b_p_fixeol && buf->b_p_eof)
{
// write trailing CTRL-Z
(void)write_eintr(write_info.bw_fd, "\x1a", 1);
nchars++;
}
// Stop when writing done or an error was encountered. // Stop when writing done or an error was encountered.
if (!checking_conversion || end == 0) if (!checking_conversion || end == 0)
break; break;

View File

@@ -2271,27 +2271,32 @@ failed:
if (error && read_count == 0) if (error && read_count == 0)
error = FALSE; error = FALSE;
/* // In Dos format ignore a trailing CTRL-Z, unless 'binary' is set.
* If we get EOF in the middle of a line, note the fact and // In old days the file length was in sector count and the CTRL-Z the
* complete the line ourselves. // marker where the file really ended. Assuming we write it to a file
* In Dos format ignore a trailing CTRL-Z, unless 'binary' set. // system that keeps file length properly the CTRL-Z should be dropped.
*/ // Set the 'endoffile' option so the user can decide what to write later.
// In Unix format the CTRL-Z is just another character.
if (linerest != 0
&& !curbuf->b_p_bin
&& fileformat == EOL_DOS
&& ptr[-1] == Ctrl_Z)
{
ptr--;
linerest--;
if (set_options)
curbuf->b_p_eof = TRUE;
}
// If we get EOF in the middle of a line, note the fact by resetting
// 'endofline' and add the line normally.
if (!error if (!error
&& !got_int && !got_int
&& linerest != 0 && linerest != 0)
// TODO: should we handle CTRL-Z differently here for 'endoffile'?
&& !(!curbuf->b_p_bin
&& fileformat == EOL_DOS
&& *line_start == Ctrl_Z
&& ptr == line_start + 1))
{ {
// remember for when writing // remember for when writing
if (set_options) if (set_options)
{
curbuf->b_p_eol = FALSE; curbuf->b_p_eol = FALSE;
if (*line_start == Ctrl_Z && ptr == line_start + 1)
curbuf->b_p_eof = TRUE;
}
*ptr = NUL; *ptr = NUL;
len = (colnr_T)(ptr - line_start + 1); len = (colnr_T)(ptr - line_start + 1);
if (ml_append(lnum, line_start, len, newfile) == FAIL) if (ml_append(lnum, line_start, len, newfile) == FAIL)

View File

@@ -48,4 +48,71 @@ func Test_fixeol()
enew! enew!
endfunc endfunc
func Test_eof()
let data = 0z68656c6c6f.0d0a.776f726c64 " "hello\r\nworld"
" 1. Eol, Eof
" read
call writefile(data + 0z0d0a.1a, 'XXEolEof')
e! XXEolEof
call assert_equal(['hello', 'world'], getline(1, 2))
call assert_equal([1, 1], [&eol, &eof])
" write
set fixeol
w!
call assert_equal(data + 0z0d0a, readblob('XXEolEof'))
set nofixeol
w!
call assert_equal(data + 0z0d0a.1a, readblob('XXEolEof'))
" 2. NoEol, Eof
" read
call writefile(data + 0z1a, 'XXNoEolEof')
e! XXNoEolEof
call assert_equal(['hello', 'world'], getline(1, 2))
call assert_equal([0, 1], [&eol, &eof])
" write
set fixeol
w!
call assert_equal(data + 0z0d0a, readblob('XXNoEolEof'))
set nofixeol
w!
call assert_equal(data + 0z1a, readblob('XXNoEolEof'))
" 3. Eol, NoEof
" read
call writefile(data + 0z0d0a, 'XXEolNoEof')
e! XXEolNoEof
call assert_equal(['hello', 'world'], getline(1, 2))
call assert_equal([1, 0], [&eol, &eof])
" write
set fixeol
w!
call assert_equal(data + 0z0d0a, readblob('XXEolNoEof'))
set nofixeol
w!
call assert_equal(data + 0z0d0a, readblob('XXEolNoEof'))
" 4. NoEol, NoEof
" read
call writefile(data, 'XXNoEolNoEof')
e! XXNoEolNoEof
call assert_equal(['hello', 'world'], getline(1, 2))
call assert_equal([0, 0], [&eol, &eof])
" write
set fixeol
w!
call assert_equal(data + 0z0d0a, readblob('XXNoEolNoEof'))
set nofixeol
w!
call assert_equal(data, readblob('XXNoEolNoEof'))
call delete('XXEolEof')
call delete('XXNoEolEof')
call delete('XXEolNoEof')
call delete('XXNoEolNoEof')
set ff& fixeol& eof& eol&
enew!
endfunc
" vim: shiftwidth=2 sts=2 expandtab " vim: shiftwidth=2 sts=2 expandtab

View File

@@ -695,6 +695,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
826,
/**/ /**/
825, 825,
/**/ /**/