diff options
-rw-r--r-- | runtime/doc/change.txt | 7 | ||||
-rw-r--r-- | runtime/doc/index.txt | 4 | ||||
-rw-r--r-- | runtime/doc/quickfix.txt | 5 | ||||
-rw-r--r-- | runtime/doc/visual.txt | 1 | ||||
-rw-r--r-- | src/nvim/buffer.c | 2 | ||||
-rw-r--r-- | src/nvim/eval.c | 2 | ||||
-rw-r--r-- | src/nvim/fileio.c | 2 | ||||
-rw-r--r-- | src/nvim/mbyte.c | 41 | ||||
-rw-r--r-- | src/nvim/normal.c | 12 | ||||
-rw-r--r-- | src/nvim/ops.c | 18 | ||||
-rw-r--r-- | src/nvim/quickfix.c | 74 | ||||
-rw-r--r-- | src/nvim/testdir/test_quickfix.vim | 23 | ||||
-rw-r--r-- | src/nvim/testdir/test_visual.vim | 58 | ||||
-rw-r--r-- | src/nvim/testdir/test_writefile.vim | 148 | ||||
-rw-r--r-- | test/functional/editor/put_spec.lua | 12 |
15 files changed, 350 insertions, 59 deletions
diff --git a/runtime/doc/change.txt b/runtime/doc/change.txt index e26a84f80f..b4d3304880 100644 --- a/runtime/doc/change.txt +++ b/runtime/doc/change.txt @@ -1118,8 +1118,11 @@ register. With blockwise selection it also depends on the size of the block and whether the corners are on an existing character. (Implementation detail: it actually works by first putting the register after the selection and then deleting the selection.) -The previously selected text is put in the unnamed register. If you want to -put the same text into a Visual selection several times you need to use +With 'p' the previously selected text is put in the unnamed register. This is +useful if you want to put that text somewhere else. But you cannot repeat the +same change. +With 'P' the unnamed register is not changed, you can repeat the same change. +But the deleted text cannot be used. If you do need it you can use 'p' with another register. E.g., yank the text to copy, Visually select the text to replace and use "0p . You can repeat this as many times as you like, and the unnamed register will be changed each time. diff --git a/runtime/doc/index.txt b/runtime/doc/index.txt index f02f9f8032..e3bc3d5437 100644 --- a/runtime/doc/index.txt +++ b/runtime/doc/index.txt @@ -923,7 +923,9 @@ tag command note action in Visual mode ~ before the highlighted area |v_J| J 2 join the highlighted lines |v_K| K run 'keywordprg' on the highlighted area -|v_O| O move horizontally to other corner of area. +|v_O| O move horizontally to other corner of area +|v_P| P replace highlighted area with register + contents; unnamed register is unchanged Q does not start Ex mode |v_R| R 2 delete the highlighted lines and start insert diff --git a/runtime/doc/quickfix.txt b/runtime/doc/quickfix.txt index ed736ad4eb..5b68da8be9 100644 --- a/runtime/doc/quickfix.txt +++ b/runtime/doc/quickfix.txt @@ -1339,12 +1339,17 @@ Basic items %f file name (finds a string) %o module name (finds a string) %l line number (finds a number) + %e end line number (finds a number) %c column number (finds a number representing character column of the error, byte index, a <tab> is 1 character column) %v virtual column number (finds a number representing screen column of the error (1 <tab> == 8 screen columns)) + %k end column number (finds a number representing + the character column of the error, byte index, or a + number representing screen end column of the error if + it's used with %v) %t error type (finds a single character): e - error message w - warning message diff --git a/runtime/doc/visual.txt b/runtime/doc/visual.txt index 5563a56216..4d5366a41a 100644 --- a/runtime/doc/visual.txt +++ b/runtime/doc/visual.txt @@ -255,6 +255,7 @@ Additionally the following commands can be used: X delete (2) |v_X| Y yank (2) |v_Y| p put |v_p| + P put without unnamed register overwrite |v_P| J join (1) |v_J| U make uppercase |v_U| u make lowercase |v_u| diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index bb8483f644..96ddd9a2f5 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -3327,7 +3327,7 @@ void maketitle(void) len = (int)STRLEN(buf_p); if (len > 100) { len -= 100; - len += (*mb_tail_off)(buf_p, buf_p + len) + 1; + len += mb_tail_off(buf_p, buf_p + len) + 1; buf_p += len; } STRCPY(icon_str, buf_p); diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 926c385892..c197754685 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -10700,7 +10700,7 @@ repeat: pbuf = NULL; // Need full path first (use expand_env() to remove a "~/") if (!has_fullname && !has_homerelative) { - if ((c == '.' || c == '~') && **fnamep == '~') { + if (**fnamep == '~') { p = pbuf = expand_env_save(*fnamep); } else { p = pbuf = (char_u *)FullName_save((char *)*fnamep, FALSE); 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/mbyte.c b/src/nvim/mbyte.c index 7fa2562be0..e5fa80a242 100644 --- a/src/nvim/mbyte.c +++ b/src/nvim/mbyte.c @@ -1821,12 +1821,10 @@ void mb_copy_char(const char_u **const fp, char_u **const tp) *fp += l; } -/* - * Return the offset from "p" to the first byte of a character. When "p" is - * at the start of a character 0 is returned, otherwise the offset to the next - * character. Can start anywhere in a stream of bytes. - */ -int mb_off_next(char_u *base, char_u *p) +/// Return the offset from "p" to the first byte of a character. When "p" is +/// at the start of a character 0 is returned, otherwise the offset to the next +/// character. Can start anywhere in a stream of bytes. +int mb_off_next(const char_u *base, const char_u *p) { int i; int j; @@ -1854,7 +1852,7 @@ int mb_off_next(char_u *base, char_u *p) /// Return the offset from "p" to the last byte of the character it points /// into. Can start anywhere in a stream of bytes. /// Composing characters are not included. -int mb_tail_off(char_u *base, char_u *p) +int mb_tail_off(const char_u *base, const char_u *p) { int i; int j; @@ -1882,12 +1880,13 @@ int mb_tail_off(char_u *base, char_u *p) /// Return the offset from "p" to the first byte of the character it points /// into. Can start anywhere in a stream of bytes. +/// Unlike utf_head_off() this doesn't include composing characters and returns a negative value. /// /// @param[in] base Pointer to start of string /// @param[in] p Pointer to byte for which to return the offset to the previous codepoint // /// @return 0 if invalid sequence, else offset to previous codepoint -int mb_head_off(char_u *base, char_u *p) +int mb_head_off(const char_u *base, const char_u *p) { int i; int j; @@ -2037,13 +2036,11 @@ char_u *mb_prevptr(char_u *line, char_u *p) return p; } -/* - * Return the character length of "str". Each multi-byte character (with - * following composing characters) counts as one. - */ -int mb_charlen(char_u *str) +/// Return the character length of "str". Each multi-byte character (with +/// following composing characters) counts as one. +int mb_charlen(const char_u *str) { - char_u *p = str; + const char_u *p = str; int count; if (p == NULL) { @@ -2057,12 +2054,10 @@ int mb_charlen(char_u *str) return count; } -/* - * Like mb_charlen() but for a string with specified length. - */ -int mb_charlen_len(char_u *str, int len) +/// Like mb_charlen() but for a string with specified length. +int mb_charlen_len(const char_u *str, int len) { - char_u *p = str; + const char_u *p = str; int count; for (count = 0; *p != NUL && p < str + len; count++) { @@ -2201,11 +2196,9 @@ char_u *enc_canonize(char_u *enc) FUNC_ATTR_NONNULL_RET return r; } -/* - * Search for an encoding alias of "name". - * Returns -1 when not found. - */ -static int enc_alias_search(char_u *name) +/// Search for an encoding alias of "name". +/// Returns -1 when not found. +static int enc_alias_search(const char_u *name) { int i; diff --git a/src/nvim/normal.c b/src/nvim/normal.c index 225c66aae1..21c465434a 100644 --- a/src/nvim/normal.c +++ b/src/nvim/normal.c @@ -7509,9 +7509,9 @@ static void nv_put_opt(cmdarg_T *cap, bool fix_indent) // overwrites if the old contents is being put. was_visual = true; regname = cap->oap->regname; + bool save_unnamed = cap->cmdchar == 'P'; // '+' and '*' could be the same selection - bool clipoverwrite = (regname == '+' || regname == '*') - && (cb_flags & CB_UNNAMEDMASK); + bool clipoverwrite = (regname == '+' || regname == '*') && (cb_flags & CB_UNNAMEDMASK); if (regname == 0 || regname == '"' || clipoverwrite || ascii_isdigit(regname) || regname == '-') { // The delete might overwrite the register we want to put, save it first @@ -7524,6 +7524,10 @@ static void nv_put_opt(cmdarg_T *cap, bool fix_indent) // do_put(), which requires the visual selection to still be active. if (!VIsual_active || VIsual_mode == 'V' || regname != '.') { // Now delete the selected text. Avoid messages here. + yankreg_T *old_y_previous; + if (save_unnamed) { + old_y_previous = get_y_previous(); + } cap->cmdchar = 'd'; cap->nchar = NUL; cap->oap->regname = NUL; @@ -7533,6 +7537,10 @@ static void nv_put_opt(cmdarg_T *cap, bool fix_indent) empty = (curbuf->b_ml.ml_flags & ML_EMPTY); msg_silent--; + if (save_unnamed) { + set_y_previous(old_y_previous); + } + // delete PUT_LINE_BACKWARD; cap->oap->regname = regname; } diff --git a/src/nvim/ops.c b/src/nvim/ops.c index b8b639265c..cf1fd29c9e 100644 --- a/src/nvim/ops.c +++ b/src/nvim/ops.c @@ -135,10 +135,18 @@ static char opchars[][3] = { Ctrl_X, NUL, OPF_CHANGE }, // OP_NR_SUB }; -/* - * Translate a command name into an operator type. - * Must only be called with a valid operator name! - */ +yankreg_T *get_y_previous(void) +{ + return y_previous; +} + +void set_y_previous(yankreg_T *yreg) +{ + y_previous = yreg; +} + +/// Translate a command name into an operator type. +/// Must only be called with a valid operator name! int get_op_type(int char1, int char2) { int i; @@ -566,7 +574,7 @@ static void block_insert(oparg_T *oap, char_u *s, int b_insert, struct block_def if (b_insert) { off = utf_head_off(oldp, oldp + offset + spaces); } else { - off = (*mb_off_next)(oldp, oldp + offset); + off = mb_off_next(oldp, oldp + offset); offset += off; } spaces -= off; diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index d4b71994cc..b12f407460 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -131,7 +131,7 @@ struct qf_info_S { static qf_info_T ql_info; // global quickfix list static unsigned last_qf_id = 0; // Last Used quickfix list id -#define FMT_PATTERNS 11 // maximum number of % recognized +#define FMT_PATTERNS 13 // maximum number of % recognized // Structure used to hold the info of one part of 'errorformat' typedef struct efm_S efm_T; @@ -332,22 +332,27 @@ int qf_init(win_T *wp, const char_u *restrict efile, char_u *restrict errorforma // Maximum number of bytes allowed per line while reading an errorfile. static const size_t LINE_MAXLEN = 4096; +/// Patterns used. Keep in sync with qf_parse_fmt[]. static struct fmtpattern { char_u convchar; char *pattern; } fmt_pat[FMT_PATTERNS] = { - { 'f', ".\\+" }, // only used when at end - { 'n', "\\d\\+" }, - { 'l', "\\d\\+" }, - { 'c', "\\d\\+" }, - { 't', "." }, - { 'm', ".\\+" }, - { 'r', ".*" }, - { 'p', "[- .]*"}, // NOLINT(whitespace/tab) - { 'v', "\\d\\+" }, - { 's', ".\\+" }, - { 'o', ".\\+" } + { 'f', ".\\+" }, // only used when at end + { 'n', "\\d\\+" }, // 1 + { 'l', "\\d\\+" }, // 2 + { 'e', "\\d\\+" }, // 3 + { 'c', "\\d\\+" }, // 4 + { 'k', "\\d\\+" }, // 5 + { 't', "." }, // 6 +#define FMT_PATTERN_M 7 + { 'm', ".\\+" }, // 7 +#define FMT_PATTERN_R 8 + { 'r', ".*" }, // 8 + { 'p', "[- \t.]*" }, // 9 + { 'v', "\\d\\+" }, // 10 + { 's', ".\\+" }, // 11 + { 'o', ".\\+" } // 12 }; /// Convert an errorformat pattern to a regular expression pattern. @@ -363,9 +368,9 @@ static char_u *efmpat_to_regpat(const char_u *efmpat, char_u *regpat, efm_T *efm semsg(_("E372: Too many %%%c in format string"), *efmpat); return NULL; } - if ((idx && idx < 6 + if ((idx && idx < FMT_PATTERN_R && vim_strchr((char_u *)"DXOPQ", efminfo->prefix) != NULL) - || (idx == 6 + || (idx == FMT_PATTERN_R && vim_strchr((char_u *)"OPQ", efminfo->prefix) == NULL)) { semsg(_("E373: Unexpected %%%c in format string"), *efmpat); return NULL; @@ -1288,7 +1293,7 @@ static int qf_parse_fmt_n(regmatch_T *rmp, int midx, qffields_T *fields) return QF_OK; } -/// Parse the match for line number (%l') pattern in regmatch. +/// Parse the match for line number ('%l') pattern in regmatch. /// Return the matched value in "fields->lnum". static int qf_parse_fmt_l(regmatch_T *rmp, int midx, qffields_T *fields) { @@ -1299,6 +1304,17 @@ static int qf_parse_fmt_l(regmatch_T *rmp, int midx, qffields_T *fields) return QF_OK; } +/// Parse the match for end line number ('%e') pattern in regmatch. +/// Return the matched value in "fields->end_lnum". +static int qf_parse_fmt_e(regmatch_T *rmp, int midx, qffields_T *fields) +{ + if (rmp->startp[midx] == NULL) { + return QF_FAIL; + } + fields->end_lnum = atol((char *)rmp->startp[midx]); + return QF_OK; +} + /// Parse the match for column number ('%c') pattern in regmatch. /// Return the matched value in "fields->col". static int qf_parse_fmt_c(regmatch_T *rmp, int midx, qffields_T *fields) @@ -1310,6 +1326,17 @@ static int qf_parse_fmt_c(regmatch_T *rmp, int midx, qffields_T *fields) return QF_OK; } +/// Parse the match for end line number ('%e') pattern in regmatch. +/// Return the matched value in "fields->end_lnum". +static int qf_parse_fmt_k(regmatch_T *rmp, int midx, qffields_T *fields) +{ + if (rmp->startp[midx] == NULL) { + return QF_FAIL; + } + fields->end_col = (int)atol((char *)rmp->startp[midx]); + return QF_OK; +} + /// Parse the match for error type ('%t') pattern in regmatch. /// Return the matched value in "fields->type". static int qf_parse_fmt_t(regmatch_T *rmp, int midx, qffields_T *fields) @@ -1442,14 +1469,17 @@ static int qf_parse_fmt_o(regmatch_T *rmp, int midx, qffields_T *fields) /// 'errorformat' format pattern parser functions. /// The '%f' and '%r' formats are parsed differently from other formats. /// See qf_parse_match() for details. +/// Keep in sync with fmt_pat[]. static int (*qf_parse_fmt[FMT_PATTERNS])(regmatch_T *, int, qffields_T *) = { - NULL, + NULL, // %f qf_parse_fmt_n, qf_parse_fmt_l, + qf_parse_fmt_e, qf_parse_fmt_c, + qf_parse_fmt_k, qf_parse_fmt_t, qf_parse_fmt_m, - NULL, + NULL, // %r qf_parse_fmt_p, qf_parse_fmt_v, qf_parse_fmt_s, @@ -1485,13 +1515,13 @@ static int qf_parse_match(char_u *linebuf, size_t linelen, efm_T *fmt_ptr, regma midx = (int)fmt_ptr->addr[i]; if (i == 0 && midx > 0) { // %f status = qf_parse_fmt_f(regmatch, midx, fields, idx); - } else if (i == 5) { + } else if (i == FMT_PATTERN_M) { if (fmt_ptr->flags == '+' && !qf_multiscan) { // %+ qf_parse_fmt_plus(linebuf, linelen, fields); } else if (midx > 0) { // %m status = qf_parse_fmt_m(regmatch, midx, fields); } - } else if (i == 6 && midx > 0) { // %r + } else if (i == FMT_PATTERN_R && midx > 0) { // %r status = qf_parse_fmt_r(regmatch, midx, tail); } else if (midx > 0) { // others status = (qf_parse_fmt[i])(regmatch, midx, fields); @@ -1636,10 +1666,16 @@ static int qf_parse_multiline_pfx(int idx, qf_list_T *qfl, qffields_T *fields) if (!qfprev->qf_lnum) { qfprev->qf_lnum = fields->lnum; } + if (!qfprev->qf_end_lnum) { + qfprev->qf_end_lnum = fields->end_lnum; + } if (!qfprev->qf_col) { qfprev->qf_col = fields->col; qfprev->qf_viscol = fields->use_viscol; } + if (!qfprev->qf_end_col) { + qfprev->qf_end_col = fields->end_col; + } if (!qfprev->qf_fnum) { qfprev->qf_fnum = qf_get_fnum(qfl, qfl->qf_directory, *fields->namebuf || qfl->qf_directory diff --git a/src/nvim/testdir/test_quickfix.vim b/src/nvim/testdir/test_quickfix.vim index 00679e1958..c4d70fb1de 100644 --- a/src/nvim/testdir/test_quickfix.vim +++ b/src/nvim/testdir/test_quickfix.vim @@ -1384,6 +1384,29 @@ func Test_efm_error_type() let &efm = save_efm endfunc +" Test for end_lnum ('%e') and end_col ('%k') fields in 'efm' +func Test_efm_end_lnum_col() + let save_efm = &efm + + " single line + set efm=%f:%l-%e:%c-%k:%t:%m + cexpr ["Xfile1:10-20:1-2:E:msg1", "Xfile1:20-30:2-3:W:msg2",] + let output = split(execute('clist'), "\n") + call assert_equal([ + \ ' 1 Xfile1:10-20 col 1-2 error: msg1', + \ ' 2 Xfile1:20-30 col 2-3 warning: msg2'], output) + + " multiple lines + set efm=%A%n)%m,%Z%f:%l-%e:%c-%k + cexpr ["1)msg1", "Xfile1:14-24:1-2", + \ "2)msg2", "Xfile1:24-34:3-4"] + let output = split(execute('clist'), "\n") + call assert_equal([ + \ ' 1 Xfile1:14-24 col 1-2 error 1: msg1', + \ ' 2 Xfile1:24-34 col 3-4 error 2: msg2'], output) + let &efm = save_efm +endfunc + func XquickfixChangedByAutocmd(cchar) call s:setup_commands(a:cchar) if a:cchar == 'c' diff --git a/src/nvim/testdir/test_visual.vim b/src/nvim/testdir/test_visual.vim index 76274fb038..099a90643f 100644 --- a/src/nvim/testdir/test_visual.vim +++ b/src/nvim/testdir/test_visual.vim @@ -1184,8 +1184,66 @@ func Test_visual_undo_deletes_last_line() exe "normal ggvjfxO" undo normal gNU + bwipe! endfunc +func Test_visual_paste() + new + + " v_p overwrites unnamed register. + call setline(1, ['xxxx']) + call setreg('"', 'foo') + call setreg('-', 'bar') + normal gg0vp + call assert_equal('x', @") + call assert_equal('x', @-) + call assert_equal('fooxxx', getline(1)) + normal $vp + call assert_equal('x', @") + call assert_equal('x', @-) + call assert_equal('fooxxx', getline(1)) + " Test with a different register as unnamed register. + call setline(2, ['baz']) + normal 2gg0"rD + call assert_equal('baz', @") + normal gg0vp + call assert_equal('f', @") + call assert_equal('f', @-) + call assert_equal('bazooxxx', getline(1)) + normal $vp + call assert_equal('x', @") + call assert_equal('x', @-) + call assert_equal('bazooxxf', getline(1)) + + if has('clipboard') + " v_P does not overwrite unnamed register. + call setline(1, ['xxxx']) + call setreg('"', 'foo') + call setreg('-', 'bar') + normal gg0vP + call assert_equal('foo', @") + call assert_equal('x', @-) + call assert_equal('fooxxx', getline(1)) + normal $vP + call assert_equal('foo', @") + call assert_equal('x', @-) + call assert_equal('fooxxfoo', getline(1)) + " Test with a different register as unnamed register. + call setline(2, ['baz']) + normal 2gg0"rD + call assert_equal('baz', @") + normal gg0vP + call assert_equal('baz', @") + call assert_equal('f', @-) + call assert_equal('bazooxxfoo', getline(1)) + normal $vP + call assert_equal('baz', @") + call assert_equal('o', @-) + call assert_equal('bazooxxfobaz', getline(1)) + endif + + bwipe! +endfunc " vim: shiftwidth=2 sts=2 expandtab 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 diff --git a/test/functional/editor/put_spec.lua b/test/functional/editor/put_spec.lua index fdda2be131..c367f8fdd0 100644 --- a/test/functional/editor/put_spec.lua +++ b/test/functional/editor/put_spec.lua @@ -507,7 +507,9 @@ describe('put command', function() return function(exception_table, after_redo) test_expect(exception_table, after_redo) if selection_string then - eq(selection_string, getreg('"')) + if not conversion_table.put_backwards then + eq(selection_string, getreg('"')) + end else eq('test_string"', getreg('"')) end @@ -714,7 +716,9 @@ describe('put command', function() expect_base, conversion_table) return function(exception_table, after_redo) test_expect(exception_table, after_redo) - eq('Line of words 1\n', getreg('"')) + if not conversion_table.put_backwards then + eq('Line of words 1\n', getreg('"')) + end end end local base_expect_string = [[ @@ -748,7 +752,9 @@ describe('put command', function() end, expect_base, conversion_table) return function(e,c) test_expect(e,c) - eq('Lin\nLin', getreg('"')) + if not conversion_table.put_backwards then + eq('Lin\nLin', getreg('"')) + end end end |