# HG changeset patch # User Bram Moolenaar # Date 1437135488 -7200 # Node ID 62ba356c2d4e5836c86908d2ec65e53a6e335f27 # Parent 727f3fececd8dca821fb7f6955b15014e507c710 patch 7.4.785 Problem: On some systems automatically adding the missing EOL causes problems. Setting 'binary' has too many side effects. Solution: Add the 'fixeol' option, default on. (Pavel Samarkin) diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -1,4 +1,4 @@ -*options.txt* For Vim version 7.4. Last change: 2015 Jul 10 +*options.txt* For Vim version 7.4. Last change: 2015 Jul 17 VIM REFERENCE MANUAL by Bram Moolenaar @@ -2671,15 +2671,16 @@ A jump table for the options with a shor local to buffer {not in Vi} When writing a file and this option is off and the 'binary' option - is on, no will be written for the last line in the file. This - option is automatically set when starting to edit a new file, unless - the file does not have an for the last line in the file, in - which case it is reset. Normally you don't have to set or reset this - option. When 'binary' is off the value is not used when writing the - file. When 'binary' is on it is used to remember the presence of a - 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. + is on, or 'fixeol' option is off, no 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 + 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 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. *'equalalways'* *'ea'* *'noequalalways'* *'noea'* 'equalalways' 'ea' boolean (default on) @@ -3064,6 +3065,17 @@ A jump table for the options with a shor fold:c Folded |hl-Folded| diff:c DiffDelete |hl-DiffDelete| + *'fixendofline'* *'fixeol'* *'nofixendofline'* *'nofixeol'* +'fixendofline' 'fixeol' boolean (default on) + local to buffer + {not in Vi} + When writing a file and this option is on, at the end of file + will be restored if missing. Turn this option off if you want to + preserve the situation from the original file. + When the 'binary' option is set the value of this option doesn't + matter. + See the 'endofline' option. + *'fkmap'* *'fk'* *'nofkmap'* *'nofk'* 'fkmap' 'fk' boolean (default off) *E198* global diff --git a/runtime/optwin.vim b/runtime/optwin.vim --- a/runtime/optwin.vim +++ b/runtime/optwin.vim @@ -954,6 +954,9 @@ call BinOptionL("bin") call append("$", "endofline\tlast line in the file has an end-of-line") call append("$", "\t(local to buffer)") call BinOptionL("eol") +call append("$", "fixeol\tfixes missing end-of-line at end of text file") +call append("$", "\t(local to buffer)") +call BinOptionL("fixeol") if has("multi_byte") call append("$", "bomb\tprepend a Byte Order Mark to the file") call append("$", "\t(local to buffer)") diff --git a/src/buffer.c b/src/buffer.c --- a/src/buffer.c +++ b/src/buffer.c @@ -547,6 +547,7 @@ buf_clear_file(buf) buf->b_shortname = FALSE; #endif buf->b_p_eol = TRUE; + buf->b_p_fixeol = TRUE; buf->b_start_eol = TRUE; #ifdef FEAT_MBYTE buf->b_p_bomb = FALSE; diff --git a/src/fileio.c b/src/fileio.c --- a/src/fileio.c +++ b/src/fileio.c @@ -2623,10 +2623,10 @@ failed: #endif /* - * Trick: We remember if the last line of the read didn't have - * an eol even when 'binary' is off, for when writing it again with - * 'binary' on. This is required for - * ":autocmd FileReadPost *.gz set bin|'[,']!gunzip" to work. + * We remember if the last line of the read didn't have + * an eol even when 'binary' is off, to support turning 'fixeol' off, + * or writing the read again with 'binary' on. The latter is required + * for ":autocmd FileReadPost *.gz set bin|'[,']!gunzip" to work. */ curbuf->b_no_eol_lnum = read_no_eol_lnum; @@ -4547,7 +4547,7 @@ restore_backup: /* write failed or last line has no EOL: stop here */ if (end == 0 || (lnum == end - && write_bin + && (write_bin || !buf->b_p_fixeol) && (lnum == buf->b_no_eol_lnum || (lnum == buf->b_ml.ml_line_count && !buf->b_p_eol)))) { diff --git a/src/memline.c b/src/memline.c --- a/src/memline.c +++ b/src/memline.c @@ -5361,8 +5361,10 @@ ml_find_line_or_offset(buf, lnum, offp) if (ffdos) size += lnum - 1; - /* Don't count the last line break if 'bin' and 'noeol'. */ - if (buf->b_p_bin && !buf->b_p_eol && buf->b_ml.ml_line_count == lnum) + /* Don't count the last line break if 'noeol' and ('bin' or + * 'nofixeol'). */ + if ((!buf->b_p_fixeol || buf->b_p_bin) && !buf->b_p_eol + && buf->b_ml.ml_line_count == lnum) size -= ffdos + 1; } diff --git a/src/netbeans.c b/src/netbeans.c --- a/src/netbeans.c +++ b/src/netbeans.c @@ -3802,7 +3802,7 @@ get_buf_size(buf_T *bufp) } } /* Correction for when last line doesn't have an EOL. */ - if (!bufp->b_p_eol && bufp->b_p_bin) + if (!bufp->b_p_eol && (bufp->b_p_bin || !bufp->b_p_fixeol)) char_count -= eol_size; } diff --git a/src/ops.c b/src/ops.c --- a/src/ops.c +++ b/src/ops.c @@ -7052,7 +7052,7 @@ cursor_pos_info() &char_count_cursor, len, eol_size); if (lnum == curbuf->b_ml.ml_line_count && !curbuf->b_p_eol - && curbuf->b_p_bin + && (curbuf->b_p_bin || !curbuf->b_p_fixeol) && (long)STRLEN(s) < len) byte_count_cursor -= eol_size; } @@ -7076,7 +7076,7 @@ cursor_pos_info() } /* Correction for when last line doesn't have an EOL. */ - if (!curbuf->b_p_eol && curbuf->b_p_bin) + if (!curbuf->b_p_eol && (curbuf->b_p_bin || !curbuf->b_p_fixeol)) byte_count -= eol_size; if (VIsual_active) diff --git a/src/option.c b/src/option.c --- a/src/option.c +++ b/src/option.c @@ -98,6 +98,7 @@ # define PV_INC OPT_BOTH(OPT_BUF(BV_INC)) #endif #define PV_EOL OPT_BUF(BV_EOL) +#define PV_FIXEOL OPT_BUF(BV_FIXEOL) #define PV_EP OPT_BOTH(OPT_BUF(BV_EP)) #define PV_ET OPT_BUF(BV_ET) #ifdef FEAT_MBYTE @@ -306,6 +307,7 @@ static char_u *p_cfu; static char_u *p_ofu; #endif static int p_eol; +static int p_fixeol; static int p_et; #ifdef FEAT_MBYTE static char_u *p_fenc; @@ -1169,6 +1171,9 @@ static struct vimoption {(char_u *)"", (char_u *)0L} #endif SCRIPTID_INIT}, + {"fixendofline", "fixeol", P_BOOL|P_VI_DEF|P_RSTAT, + (char_u *)&p_fixeol, PV_FIXEOL, + {(char_u *)TRUE, (char_u *)0L} SCRIPTID_INIT}, {"fkmap", "fk", P_BOOL|P_VI_DEF, #ifdef FEAT_FKMAP (char_u *)&p_fkmap, PV_NONE, @@ -7781,6 +7786,11 @@ set_bool_option(opt_idx, varp, value, op { redraw_titles(); } + /* when 'fixeol' is changed, redraw the window title */ + else if ((int *)varp == &curbuf->b_p_fixeol) + { + redraw_titles(); + } # ifdef FEAT_MBYTE /* when 'bomb' is changed, redraw the window title and tab page text */ else if ((int *)varp == &curbuf->b_p_bomb) @@ -10176,6 +10186,7 @@ get_varp(p) case PV_OFU: return (char_u *)&(curbuf->b_p_ofu); #endif case PV_EOL: return (char_u *)&(curbuf->b_p_eol); + case PV_FIXEOL: return (char_u *)&(curbuf->b_p_fixeol); case PV_ET: return (char_u *)&(curbuf->b_p_et); #ifdef FEAT_MBYTE case PV_FENC: return (char_u *)&(curbuf->b_p_fenc); @@ -11894,6 +11905,7 @@ save_file_ff(buf) * from when editing started (save_file_ff() called). * Also when 'endofline' was changed and 'binary' is set, or when 'bomb' was * changed and 'binary' is not set. + * Also when 'endofline' was changed and 'fixeol' is not set. * When "ignore_empty" is true don't consider a new, empty buffer to be * changed. */ @@ -11912,7 +11924,7 @@ file_ff_differs(buf, ignore_empty) return FALSE; if (buf->b_start_ffc != *buf->b_p_ff) return TRUE; - if (buf->b_p_bin && buf->b_start_eol != buf->b_p_eol) + if ((buf->b_p_bin || !buf->b_p_fixeol) && buf->b_start_eol != buf->b_p_eol) return TRUE; #ifdef FEAT_MBYTE if (!buf->b_p_bin && buf->b_start_bomb != buf->b_p_bomb) diff --git a/src/option.h b/src/option.h --- a/src/option.h +++ b/src/option.h @@ -962,6 +962,7 @@ enum , BV_INC #endif , BV_EOL + , BV_FIXEOL , BV_EP , BV_ET , BV_FENC diff --git a/src/os_unix.c b/src/os_unix.c --- a/src/os_unix.c +++ b/src/os_unix.c @@ -4624,7 +4624,8 @@ mch_call_shell(cmd, options) /* Finished a line, add a NL, unless this line * should not have one. */ if (lnum != curbuf->b_op_end.lnum - || !curbuf->b_p_bin + || (!curbuf->b_p_bin + && curbuf->b_p_fixeol) || (lnum != curbuf->b_no_eol_lnum && (lnum != curbuf->b_ml.ml_line_count diff --git a/src/os_win32.c b/src/os_win32.c --- a/src/os_win32.c +++ b/src/os_win32.c @@ -4173,7 +4173,8 @@ sub_process_writer(LPVOID param) /* Finished a line, add a NL, unless this line should not have * one. */ if (lnum != curbuf->b_op_end.lnum - || !curbuf->b_p_bin + || (!curbuf->b_p_bin + && curbuf->b_p_fixeol) || (lnum != curbuf->b_no_eol_lnum && (lnum != curbuf->b_ml.ml_line_count || curbuf->b_p_eol))) diff --git a/src/structs.h b/src/structs.h --- a/src/structs.h +++ b/src/structs.h @@ -635,7 +635,7 @@ typedef struct memline int ml_flags; infoptr_T *ml_stack; /* stack of pointer blocks (array of IPTRs) */ - int ml_stack_top; /* current top if ml_stack */ + int ml_stack_top; /* current top of ml_stack */ int ml_stack_size; /* total number of entries in ml_stack */ linenr_T ml_line_lnum; /* line number of cached line, 0 if not valid */ @@ -1586,6 +1586,7 @@ struct file_buffer char_u *b_p_ofu; /* 'omnifunc' */ #endif int b_p_eol; /* 'endofline' */ + int b_p_fixeol; /* 'fixendofline' */ int b_p_et; /* 'expandtab' */ int b_p_et_nobin; /* b_p_et saved for binary mode */ #ifdef FEAT_MBYTE diff --git a/src/testdir/Make_amiga.mak b/src/testdir/Make_amiga.mak --- a/src/testdir/Make_amiga.mak +++ b/src/testdir/Make_amiga.mak @@ -45,6 +45,7 @@ SCRIPTS = test1.out test3.out test4.out test_command_count.out \ test_erasebackword.out \ test_eval.out \ + test_fixeol.out \ test_increment.out \ test_insertcount.out \ test_listchars.out \ @@ -195,6 +196,7 @@ test_command_count.out: test_command_cou test_erasebackword.out: test_erasebackword.in test_eval.out: test_eval.in test_increment.out: test_increment.in +test_fixeol.out: test_fixeol.in test_insertcount.out: test_insertcount.in test_listchars.out: test_listchars.in test_listlbr.out: test_listlbr.in diff --git a/src/testdir/Make_dos.mak b/src/testdir/Make_dos.mak --- a/src/testdir/Make_dos.mak +++ b/src/testdir/Make_dos.mak @@ -44,6 +44,7 @@ SCRIPTS = test3.out test4.out test5.out test_command_count.out \ test_erasebackword.out \ test_eval.out \ + test_fixeol.out \ test_increment.out \ test_insertcount.out \ test_listchars.out \ diff --git a/src/testdir/Make_ming.mak b/src/testdir/Make_ming.mak --- a/src/testdir/Make_ming.mak +++ b/src/testdir/Make_ming.mak @@ -66,6 +66,7 @@ SCRIPTS = test3.out test4.out test5.out test_command_count.out \ test_erasebackword.out \ test_eval.out \ + test_fixeol.out \ test_increment.out \ test_insertcount.out \ test_listchars.out \ diff --git a/src/testdir/Make_os2.mak b/src/testdir/Make_os2.mak --- a/src/testdir/Make_os2.mak +++ b/src/testdir/Make_os2.mak @@ -46,6 +46,7 @@ SCRIPTS = test1.out test3.out test4.out test_command_count.out \ test_erasebackword.out \ test_eval.out \ + test_fixeol.out \ test_increment.out \ test_insertcount.out \ test_listchars.out \ diff --git a/src/testdir/Make_vms.mms b/src/testdir/Make_vms.mms --- a/src/testdir/Make_vms.mms +++ b/src/testdir/Make_vms.mms @@ -4,7 +4,7 @@ # Authors: Zoltan Arpadffy, # Sandor Kopanyi, # -# Last change: 2015 Jul 10 +# Last change: 2015 Jul 17 # # This has been tested on VMS 6.2 to 8.3 on DEC Alpha, VAX and IA64. # Edit the lines in the Configuration section below to select. @@ -105,6 +105,7 @@ SCRIPT = test1.out test2.out test3.out test_command_count.out \ test_erasebackword.out \ test_eval.out \ + test_fixeol.out \ test_increment.out \ test_insertcount.out \ test_listchars.out \ diff --git a/src/testdir/Makefile b/src/testdir/Makefile --- a/src/testdir/Makefile +++ b/src/testdir/Makefile @@ -42,6 +42,7 @@ SCRIPTS = test1.out test2.out test3.out test_command_count.out \ test_erasebackword.out \ test_eval.out \ + test_fixeol.out \ test_increment.out \ test_insertcount.out \ test_listchars.out \ diff --git a/src/testdir/test_fixeol.in b/src/testdir/test_fixeol.in new file mode 100644 --- /dev/null +++ b/src/testdir/test_fixeol.in @@ -0,0 +1,40 @@ +Tests for 'fixeol' vim: set ft=vim : + +STARTTEST +:" first write two test files – with and without trailing EOL +:" use Unix fileformat for consistency +:set ff=unix +:enew! +awith eol:w! XXEol +:enew! +:set noeol nofixeol +awithout eol:w! XXNoEol +:set eol fixeol +:bwipe XXEol XXNoEol +:" +:" try editing files with 'fixeol' disabled +:e! XXEol +ostays eol:set nofixeol +:w! XXTestEol +:e! XXNoEol +ostays without:set nofixeol +:w! XXTestNoEol +:bwipe XXEol XXNoEol XXTestEol XXTestNoEol +:set fixeol +:" +:" Append "END" to each file so that we can see what the last written char was. +ggdGaEND:w >>XXEol +:w >>XXNoEol +:w >>XXTestEol +:w >>XXTestNoEol +:" +:" Concatenate the results +:e! test.out +a0:$r XXEol +:$r XXNoEol +Go1:$r XXTestEol +:$r XXTestNoEol +:w +:qa! +ENDTEST + diff --git a/src/testdir/test_fixeol.ok b/src/testdir/test_fixeol.ok new file mode 100644 --- /dev/null +++ b/src/testdir/test_fixeol.ok @@ -0,0 +1,10 @@ +0 +with eol +END +without eolEND +1 +with eol +stays eol +END +without eol +stays withoutEND diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 785, +/**/ 784, /**/ 783,