mirror of
https://github.com/neovim/neovim.git
synced 2025-09-06 03:18:16 +00:00
Merge pull request #20855 from zeertzjq/vim-fb0cf2357e0c
vim-patch:9.0.{0816,0819}: CTRL-Z at end of file is always dropped
This commit is contained in:
@@ -2135,6 +2135,15 @@ A jump table for the options with a short description can be found at |Q_op|.
|
|||||||
|
|
||||||
See 'fileencoding' to control file-content encoding.
|
See 'fileencoding' to control file-content encoding.
|
||||||
|
|
||||||
|
*'endoffile'* *'eof'* *'noendoffile'* *'noeof'*
|
||||||
|
'endoffile' 'eof' boolean (default on)
|
||||||
|
local to buffer
|
||||||
|
Indicates that a CTRL-Z character was found at the end of the file
|
||||||
|
when reading it. Normally only happens when 'fileformat' is "dos".
|
||||||
|
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
|
||||||
|
end of the file.
|
||||||
|
|
||||||
*'endofline'* *'eol'* *'noendofline'* *'noeol'*
|
*'endofline'* *'eol'* *'noendofline'* *'noeol'*
|
||||||
'endofline' 'eol' boolean (default on)
|
'endofline' 'eol' boolean (default on)
|
||||||
local to buffer
|
local to buffer
|
||||||
|
@@ -689,6 +689,7 @@ Short explanation of each option: *option-list*
|
|||||||
'display' 'dy' list of flags for how to display text
|
'display' 'dy' list of flags for how to display text
|
||||||
'eadirection' 'ead' in which direction 'equalalways' works
|
'eadirection' 'ead' in which direction 'equalalways' works
|
||||||
'encoding' 'enc' encoding used internally
|
'encoding' 'enc' encoding used internally
|
||||||
|
'endoffile' 'eof' write CTRL-Z at end of the file
|
||||||
'endofline' 'eol' write <EOL> for last line in file
|
'endofline' 'eol' write <EOL> for last line in file
|
||||||
'equalalways' 'ea' windows are automatically made the same size
|
'equalalways' 'ea' windows are automatically made the same size
|
||||||
'equalprg' 'ep' external program to use for "=" command
|
'equalprg' 'ep' external program to use for "=" command
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
" These commands create the option window.
|
" These commands create the option window.
|
||||||
"
|
"
|
||||||
" Maintainer: Bram Moolenaar <Bram@vim.org>
|
" Maintainer: Bram Moolenaar <Bram@vim.org>
|
||||||
" Last Change: 2022 Oct 15
|
" Last Change: 2022 Oct 28
|
||||||
|
|
||||||
" If there already is an option window, jump to that one.
|
" If there already is an option window, jump to that one.
|
||||||
let buf = bufnr('option-window')
|
let buf = bufnr('option-window')
|
||||||
@@ -956,6 +956,9 @@ call <SID>BinOptionL("bin")
|
|||||||
call <SID>AddOption("endofline", gettext("last line in the file has an end-of-line"))
|
call <SID>AddOption("endofline", gettext("last line in the file has an end-of-line"))
|
||||||
call append("$", "\t" .. s:local_to_buffer)
|
call append("$", "\t" .. s:local_to_buffer)
|
||||||
call <SID>BinOptionL("eol")
|
call <SID>BinOptionL("eol")
|
||||||
|
call <SID>AddOption("endoffile", gettext("last line in the file followed by CTRL-Z"))
|
||||||
|
call append("$", "\t" .. s:local_to_buffer)
|
||||||
|
call <SID>BinOptionL("eof")
|
||||||
call <SID>AddOption("fixendofline", gettext("fixes missing end-of-line at end of text file"))
|
call <SID>AddOption("fixendofline", gettext("fixes missing end-of-line at end of text file"))
|
||||||
call append("$", "\t" .. s:local_to_buffer)
|
call append("$", "\t" .. s:local_to_buffer)
|
||||||
call <SID>BinOptionL("fixeol")
|
call <SID>BinOptionL("fixeol")
|
||||||
|
@@ -689,6 +689,8 @@ void buf_clear_file(buf_T *buf)
|
|||||||
{
|
{
|
||||||
buf->b_ml.ml_line_count = 1;
|
buf->b_ml.ml_line_count = 1;
|
||||||
unchanged(buf, true, true);
|
unchanged(buf, true, true);
|
||||||
|
buf->b_p_eof = false;
|
||||||
|
buf->b_start_eof = false;
|
||||||
buf->b_p_eol = true;
|
buf->b_p_eol = true;
|
||||||
buf->b_start_eol = true;
|
buf->b_start_eol = true;
|
||||||
buf->b_p_bomb = false;
|
buf->b_p_bomb = false;
|
||||||
|
@@ -675,6 +675,7 @@ struct file_buffer {
|
|||||||
char *b_p_cfu; ///< 'completefunc'
|
char *b_p_cfu; ///< 'completefunc'
|
||||||
char *b_p_ofu; ///< 'omnifunc'
|
char *b_p_ofu; ///< 'omnifunc'
|
||||||
char *b_p_tfu; ///< 'tagfunc'
|
char *b_p_tfu; ///< 'tagfunc'
|
||||||
|
int b_p_eof; ///< 'endoffile'
|
||||||
int b_p_eol; ///< 'endofline'
|
int b_p_eol; ///< 'endofline'
|
||||||
int b_p_fixeol; ///< 'fixendofline'
|
int b_p_fixeol; ///< 'fixendofline'
|
||||||
int b_p_et; ///< 'expandtab'
|
int b_p_et; ///< 'expandtab'
|
||||||
@@ -793,6 +794,7 @@ struct file_buffer {
|
|||||||
linenr_T b_no_eol_lnum; // non-zero lnum when last line of next binary
|
linenr_T b_no_eol_lnum; // non-zero lnum when last line of next binary
|
||||||
// write should not have an end-of-line
|
// write should not have an end-of-line
|
||||||
|
|
||||||
|
int b_start_eof; // last line had eof (CTRL-Z) when it was read
|
||||||
int b_start_eol; // last line had eol when it was read
|
int b_start_eol; // last line had eol when it was read
|
||||||
int b_start_ffc; // first char of 'ff' when edit started
|
int b_start_ffc; // first char of 'ff' when edit started
|
||||||
char *b_start_fenc; // 'fileencoding' when edit started or NULL
|
char *b_start_fenc; // 'fileencoding' when edit started or NULL
|
||||||
|
@@ -539,6 +539,7 @@ void unchanged(buf_T *buf, int ff, bool always_inc_changedtick)
|
|||||||
void save_file_ff(buf_T *buf)
|
void save_file_ff(buf_T *buf)
|
||||||
{
|
{
|
||||||
buf->b_start_ffc = (unsigned char)(*buf->b_p_ff);
|
buf->b_start_ffc = (unsigned char)(*buf->b_p_ff);
|
||||||
|
buf->b_start_eof = buf->b_p_eof;
|
||||||
buf->b_start_eol = buf->b_p_eol;
|
buf->b_start_eol = buf->b_p_eol;
|
||||||
buf->b_start_bomb = buf->b_p_bomb;
|
buf->b_start_bomb = buf->b_p_bomb;
|
||||||
|
|
||||||
@@ -573,7 +574,8 @@ bool file_ff_differs(buf_T *buf, bool ignore_empty)
|
|||||||
if (buf->b_start_ffc != *buf->b_p_ff) {
|
if (buf->b_start_ffc != *buf->b_p_ff) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if ((buf->b_p_bin || !buf->b_p_fixeol) && buf->b_start_eol != buf->b_p_eol) {
|
if ((buf->b_p_bin || !buf->b_p_fixeol)
|
||||||
|
&& (buf->b_start_eof != buf->b_p_eof || buf->b_start_eol != buf->b_p_eol)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (!buf->b_p_bin && buf->b_start_bomb != buf->b_p_bomb) {
|
if (!buf->b_p_bin && buf->b_start_bomb != buf->b_p_bomb) {
|
||||||
|
@@ -524,6 +524,8 @@ int readfile(char *fname, char *sfname, linenr_T from, linenr_T lines_to_skip,
|
|||||||
// Don't change 'eol' if reading from buffer as it will already be
|
// Don't change 'eol' if reading from buffer as it will already be
|
||||||
// correctly set when reading stdin.
|
// correctly set when reading stdin.
|
||||||
if (!read_buffer) {
|
if (!read_buffer) {
|
||||||
|
curbuf->b_p_eof = false;
|
||||||
|
curbuf->b_start_eof = false;
|
||||||
curbuf->b_p_eol = true;
|
curbuf->b_p_eol = true;
|
||||||
curbuf->b_start_eol = true;
|
curbuf->b_start_eol = true;
|
||||||
}
|
}
|
||||||
@@ -1628,6 +1630,7 @@ failed:
|
|||||||
if (!error
|
if (!error
|
||||||
&& !got_int
|
&& !got_int
|
||||||
&& linerest != 0
|
&& linerest != 0
|
||||||
|
// TODO(vim): should we handle CTRL-Z differently here for 'endoffile'?
|
||||||
&& !(!curbuf->b_p_bin
|
&& !(!curbuf->b_p_bin
|
||||||
&& fileformat == EOL_DOS
|
&& fileformat == EOL_DOS
|
||||||
&& *line_start == Ctrl_Z
|
&& *line_start == Ctrl_Z
|
||||||
@@ -1635,6 +1638,9 @@ failed:
|
|||||||
// 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);
|
||||||
@@ -3191,6 +3197,11 @@ 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
|
||||||
|
@@ -3978,6 +3978,8 @@ static char_u *get_varp(vimoption_T *p)
|
|||||||
return (char_u *)&(curbuf->b_p_cfu);
|
return (char_u *)&(curbuf->b_p_cfu);
|
||||||
case PV_OFU:
|
case PV_OFU:
|
||||||
return (char_u *)&(curbuf->b_p_ofu);
|
return (char_u *)&(curbuf->b_p_ofu);
|
||||||
|
case PV_EOF:
|
||||||
|
return (char_u *)&(curbuf->b_p_eof);
|
||||||
case PV_EOL:
|
case PV_EOL:
|
||||||
return (char_u *)&(curbuf->b_p_eol);
|
return (char_u *)&(curbuf->b_p_eol);
|
||||||
case PV_FIXEOL:
|
case PV_FIXEOL:
|
||||||
|
@@ -497,6 +497,7 @@ EXTERN char_u *p_ef; // 'errorfile'
|
|||||||
EXTERN char *p_efm; // 'errorformat'
|
EXTERN char *p_efm; // 'errorformat'
|
||||||
EXTERN char *p_gefm; // 'grepformat'
|
EXTERN char *p_gefm; // 'grepformat'
|
||||||
EXTERN char *p_gp; // 'grepprg'
|
EXTERN char *p_gp; // 'grepprg'
|
||||||
|
EXTERN int p_eof; ///< 'endoffile'
|
||||||
EXTERN int p_eol; ///< 'endofline'
|
EXTERN int p_eol; ///< 'endofline'
|
||||||
EXTERN char *p_ei; // 'eventignore'
|
EXTERN char *p_ei; // 'eventignore'
|
||||||
EXTERN int p_et; ///< 'expandtab'
|
EXTERN int p_et; ///< 'expandtab'
|
||||||
@@ -858,6 +859,7 @@ enum {
|
|||||||
BV_CFU,
|
BV_CFU,
|
||||||
BV_DEF,
|
BV_DEF,
|
||||||
BV_INC,
|
BV_INC,
|
||||||
|
BV_EOF,
|
||||||
BV_EOL,
|
BV_EOL,
|
||||||
BV_FIXEOL,
|
BV_FIXEOL,
|
||||||
BV_EP,
|
BV_EP,
|
||||||
|
@@ -640,6 +640,15 @@ return {
|
|||||||
varname='p_enc',
|
varname='p_enc',
|
||||||
defaults={if_true=macros('ENC_DFLT')}
|
defaults={if_true=macros('ENC_DFLT')}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
full_name='endoffile', abbreviation='eof',
|
||||||
|
short_desc=N_("write CTRL-Z for last line in file"),
|
||||||
|
type='bool', scope={'buffer'},
|
||||||
|
no_mkrc=true,
|
||||||
|
redraw={'statuslines'},
|
||||||
|
varname='p_eof',
|
||||||
|
defaults={if_true=true}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
full_name='endofline', abbreviation='eol',
|
full_name='endofline', abbreviation='eol',
|
||||||
short_desc=N_("write <EOL> for last line in file"),
|
short_desc=N_("write <EOL> for last line in file"),
|
||||||
|
@@ -1,16 +1,17 @@
|
|||||||
" Tests for 'fixeol' and 'eol'
|
" Tests for 'fixeol', 'eof' and 'eol'
|
||||||
|
|
||||||
func Test_fixeol()
|
func Test_fixeol()
|
||||||
" first write two test files – with and without trailing EOL
|
" first write two test files – with and without trailing EOL
|
||||||
" use Unix fileformat for consistency
|
" use Unix fileformat for consistency
|
||||||
set ff=unix
|
set ff=unix
|
||||||
enew!
|
enew!
|
||||||
call setline('.', 'with eol')
|
call setline('.', 'with eol or eof')
|
||||||
w! XXEol
|
w! XXEol
|
||||||
enew!
|
enew!
|
||||||
set noeol nofixeol
|
set noeof noeol nofixeol
|
||||||
call setline('.', 'without eol')
|
call setline('.', 'without eol or eof')
|
||||||
w! XXNoEol
|
w! XXNoEol
|
||||||
set eol fixeol
|
set eol eof fixeol
|
||||||
bwipe XXEol XXNoEol
|
bwipe XXEol XXNoEol
|
||||||
|
|
||||||
" try editing files with 'fixeol' disabled
|
" try editing files with 'fixeol' disabled
|
||||||
@@ -33,16 +34,18 @@ func Test_fixeol()
|
|||||||
w >>XXTestEol
|
w >>XXTestEol
|
||||||
w >>XXTestNoEol
|
w >>XXTestNoEol
|
||||||
|
|
||||||
call assert_equal(['with eol', 'END'], readfile('XXEol'))
|
call assert_equal(['with eol or eof', 'END'], readfile('XXEol'))
|
||||||
call assert_equal(['without eolEND'], readfile('XXNoEol'))
|
call assert_equal(['without eol or eofEND'], readfile('XXNoEol'))
|
||||||
call assert_equal(['with eol', 'stays eol', 'END'], readfile('XXTestEol'))
|
call assert_equal(['with eol or eof', 'stays eol', 'END'], readfile('XXTestEol'))
|
||||||
call assert_equal(['without eol', 'stays withoutEND'],
|
call assert_equal(['without eol or eof', 'stays withoutEND'],
|
||||||
\ readfile('XXTestNoEol'))
|
\ readfile('XXTestNoEol'))
|
||||||
|
|
||||||
call delete('XXEol')
|
call delete('XXEol')
|
||||||
call delete('XXNoEol')
|
call delete('XXNoEol')
|
||||||
call delete('XXTestEol')
|
call delete('XXTestEol')
|
||||||
call delete('XXTestNoEol')
|
call delete('XXTestNoEol')
|
||||||
set ff& fixeol& eol&
|
set ff& fixeol& eof& eol&
|
||||||
enew!
|
enew!
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
" vim: shiftwidth=2 sts=2 expandtab
|
||||||
|
Reference in New Issue
Block a user