diff options
-rw-r--r-- | src/nvim/fileio.c | 2 | ||||
-rw-r--r-- | src/nvim/testdir/test_writefile.vim | 148 |
2 files changed, 149 insertions, 1 deletions
diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c index f28ee1bfcb..8e1be3bbf7 100644 --- a/src/nvim/fileio.c +++ b/src/nvim/fileio.c @@ -3318,7 +3318,7 @@ restore_backup: if (end == 0 || (lnum == end && (write_bin || !buf->b_p_fixeol) - && (lnum == buf->b_no_eol_lnum + && ((write_bin && lnum == buf->b_no_eol_lnum) || (lnum == buf->b_ml.ml_line_count && !buf->b_p_eol)))) { lnum++; // written the line, count it no_eol = true; diff --git a/src/nvim/testdir/test_writefile.vim b/src/nvim/testdir/test_writefile.vim index 1d9fc6e3f7..b42665c9b5 100644 --- a/src/nvim/testdir/test_writefile.vim +++ b/src/nvim/testdir/test_writefile.vim @@ -369,6 +369,154 @@ func Test_write_file_encoding() %bw! endfunc +" Test for writing and reading a file starting with a BOM. +" Byte Order Mark (BOM) character for various encodings is below: +" UTF-8 : EF BB BF +" UTF-16 (BE): FE FF +" UTF-16 (LE): FF FE +" UTF-32 (BE): 00 00 FE FF +" UTF-32 (LE): FF FE 00 00 +func Test_readwrite_file_with_bom() + let utf8_bom = "\xEF\xBB\xBF" + let utf16be_bom = "\xFE\xFF" + let utf16le_bom = "\xFF\xFE" + let utf32be_bom = "\n\n\xFE\xFF" + let utf32le_bom = "\xFF\xFE\n\n" + let save_fileencoding = &fileencoding + set cpoptions+=S + + " Check that editing a latin1 file doesn't see a BOM + call writefile(["\xFE\xFElatin-1"], 'Xtest1') + edit Xtest1 + call assert_equal('latin1', &fileencoding) + call assert_equal(0, &bomb) + set fenc=latin1 + write Xfile2 + call assert_equal(["\xFE\xFElatin-1", ''], readfile('Xfile2', 'b')) + set bomb fenc=latin1 + write Xtest3 + call assert_equal(["\xFE\xFElatin-1", ''], readfile('Xtest3', 'b')) + set bomb& + + " Check utf-8 BOM + %bw! + call writefile([utf8_bom .. "utf-8"], 'Xtest1') + edit! Xtest1 + call assert_equal('utf-8', &fileencoding) + call assert_equal(1, &bomb) + call assert_equal('utf-8', getline(1)) + set fenc=latin1 + write! Xfile2 + call assert_equal(['utf-8', ''], readfile('Xfile2', 'b')) + set fenc=utf-8 + w! Xtest3 + call assert_equal([utf8_bom .. "utf-8", ''], readfile('Xtest3', 'b')) + + " Check utf-8 with an error (will fall back to latin-1) + %bw! + call writefile([utf8_bom .. "utf-8\x80err"], 'Xtest1') + edit! Xtest1 + call assert_equal('latin1', &fileencoding) + call assert_equal(0, &bomb) + call assert_equal("\xC3\xAF\xC2\xBB\xC2\xBFutf-8\xC2\x80err", getline(1)) + set fenc=latin1 + write! Xfile2 + call assert_equal([utf8_bom .. "utf-8\x80err", ''], readfile('Xfile2', 'b')) + set fenc=utf-8 + w! Xtest3 + call assert_equal(["\xC3\xAF\xC2\xBB\xC2\xBFutf-8\xC2\x80err", ''], + \ readfile('Xtest3', 'b')) + + " Check ucs-2 BOM + %bw! + call writefile([utf16be_bom .. "\nu\nc\ns\n-\n2\n"], 'Xtest1') + edit! Xtest1 + call assert_equal('utf-16', &fileencoding) + call assert_equal(1, &bomb) + call assert_equal('ucs-2', getline(1)) + set fenc=latin1 + write! Xfile2 + call assert_equal(["ucs-2", ''], readfile('Xfile2', 'b')) + set fenc=ucs-2 + w! Xtest3 + call assert_equal([utf16be_bom .. "\nu\nc\ns\n-\n2\n", ''], + \ readfile('Xtest3', 'b')) + + " Check ucs-2le BOM + %bw! + call writefile([utf16le_bom .. "u\nc\ns\n-\n2\nl\ne\n"], 'Xtest1') + " Need to add a NUL byte after the NL byte + call writefile(0z00, 'Xtest1', 'a') + edit! Xtest1 + call assert_equal('utf-16le', &fileencoding) + call assert_equal(1, &bomb) + call assert_equal('ucs-2le', getline(1)) + set fenc=latin1 + write! Xfile2 + call assert_equal(["ucs-2le", ''], readfile('Xfile2', 'b')) + set fenc=ucs-2le + w! Xtest3 + call assert_equal([utf16le_bom .. "u\nc\ns\n-\n2\nl\ne\n", "\n"], + \ readfile('Xtest3', 'b')) + + " Check ucs-4 BOM + %bw! + call writefile([utf32be_bom .. "\n\n\nu\n\n\nc\n\n\ns\n\n\n-\n\n\n4\n\n\n"], 'Xtest1') + edit! Xtest1 + call assert_equal('ucs-4', &fileencoding) + call assert_equal(1, &bomb) + call assert_equal('ucs-4', getline(1)) + set fenc=latin1 + write! Xfile2 + call assert_equal(["ucs-4", ''], readfile('Xfile2', 'b')) + set fenc=ucs-4 + w! Xtest3 + call assert_equal([utf32be_bom .. "\n\n\nu\n\n\nc\n\n\ns\n\n\n-\n\n\n4\n\n\n", ''], readfile('Xtest3', 'b')) + + " Check ucs-4le BOM + %bw! + call writefile([utf32le_bom .. "u\n\n\nc\n\n\ns\n\n\n-\n\n\n4\n\n\nl\n\n\ne\n\n\n"], 'Xtest1') + " Need to add three NUL bytes after the NL byte + call writefile(0z000000, 'Xtest1', 'a') + edit! Xtest1 + call assert_equal('ucs-4le', &fileencoding) + call assert_equal(1, &bomb) + call assert_equal('ucs-4le', getline(1)) + set fenc=latin1 + write! Xfile2 + call assert_equal(["ucs-4le", ''], readfile('Xfile2', 'b')) + set fenc=ucs-4le + w! Xtest3 + call assert_equal([utf32le_bom .. "u\n\n\nc\n\n\ns\n\n\n-\n\n\n4\n\n\nl\n\n\ne\n\n\n", "\n\n\n"], readfile('Xtest3', 'b')) + + set cpoptions-=S + let &fileencoding = save_fileencoding + call delete('Xtest1') + call delete('Xfile2') + call delete('Xtest3') + %bw! +endfunc + +func Test_read_write_bin() + " write file missing EOL + call writefile(['noeol'], "XNoEolSetEol", 'bS') + call assert_equal(0z6E6F656F6C, readfile('XNoEolSetEol', 'B')) + + " when file is read 'eol' is off + set nofixeol + e! ++ff=unix XNoEolSetEol + call assert_equal(0, &eol) + + " writing with 'eol' set adds the newline + setlocal eol + w + call assert_equal(0z6E6F656F6C0A, readfile('XNoEolSetEol', 'B')) + + call delete('XNoEolSetEol') + set ff& + bwipe! XNoEolSetEol +endfunc + " Check that buffer is written before triggering QuitPre func Test_wq_quitpre_autocommand() edit Xsomefile |