diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/buffer.c | 5 | ||||
-rw-r--r-- | src/nvim/eval.c | 65 | ||||
-rw-r--r-- | src/nvim/eval.lua | 1 | ||||
-rw-r--r-- | src/nvim/fileio.c | 8 | ||||
-rw-r--r-- | src/nvim/mbyte.c | 4 | ||||
-rw-r--r-- | src/nvim/mbyte.h | 1 | ||||
-rw-r--r-- | src/nvim/quickfix.c | 12 | ||||
-rw-r--r-- | src/nvim/screen.c | 86 | ||||
-rw-r--r-- | src/nvim/tag.c | 46 | ||||
-rw-r--r-- | src/nvim/testdir/Makefile | 1 | ||||
-rw-r--r-- | src/nvim/testdir/test_alot.vim | 1 | ||||
-rw-r--r-- | src/nvim/testdir/test_autocmd.vim | 45 | ||||
-rw-r--r-- | src/nvim/testdir/test_functions.vim | 23 | ||||
-rw-r--r-- | src/nvim/testdir/test_join.vim | 35 | ||||
-rw-r--r-- | src/nvim/testdir/test_stat.vim | 93 | ||||
-rw-r--r-- | src/nvim/testdir/test_tagjump.vim | 28 | ||||
-rw-r--r-- | src/nvim/testdir/test_taglist.vim | 7 | ||||
-rw-r--r-- | src/nvim/testdir/test_user_func.vim | 96 |
18 files changed, 471 insertions, 86 deletions
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index 3fadcc75bf..00d472b4c8 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -296,6 +296,11 @@ open_buffer ( } save_file_ff(curbuf); // keep this fileformat + // Set last_changedtick to avoid triggering a TextChanged autocommand right + // after it was added. + curbuf->b_last_changedtick = buf_get_changedtick(curbuf); + curbuf->b_last_changedtick_pum = buf_get_changedtick(curbuf); + /* require "!" to overwrite the file, because it wasn't read completely */ if (aborting()) curbuf->b_flags |= BF_READERR; diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 22cb544f54..86f57ee5a2 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -9874,7 +9874,7 @@ static void f_getftype(typval_T *argvars, typval_T *rettv, FunPtr fptr) # endif # ifdef S_ISSOCK else if (S_ISSOCK(mode)) - t = "fifo"; + t = "socket"; # endif else t = "other"; @@ -17218,6 +17218,69 @@ error: return; } +// "trim({expr})" function +static void f_trim(typval_T *argvars, typval_T *rettv, FunPtr fptr) +{ + char buf1[NUMBUFLEN]; + char buf2[NUMBUFLEN]; + const char_u *head = (const char_u *)tv_get_string_buf_chk(&argvars[0], buf1); + const char_u *mask = NULL; + const char_u *tail; + const char_u *prev; + const char_u *p; + int c1; + + rettv->v_type = VAR_STRING; + if (head == NULL) { + rettv->vval.v_string = NULL; + return; + } + + if (argvars[1].v_type == VAR_STRING) { + mask = (const char_u *)tv_get_string_buf_chk(&argvars[1], buf2); + } + + while (*head != NUL) { + c1 = PTR2CHAR(head); + if (mask == NULL) { + if (c1 > ' ' && c1 != 0xa0) { + break; + } + } else { + for (p = mask; *p != NUL; MB_PTR_ADV(p)) { + if (c1 == PTR2CHAR(p)) { + break; + } + } + if (*p == NUL) { + break; + } + } + MB_PTR_ADV(head); + } + + for (tail = head + STRLEN(head); tail > head; tail = prev) { + prev = tail; + MB_PTR_BACK(head, prev); + c1 = PTR2CHAR(prev); + if (mask == NULL) { + if (c1 > ' ' && c1 != 0xa0) { + break; + } + } else { + for (p = mask; *p != NUL; MB_PTR_ADV(p)) { + if (c1 == PTR2CHAR(p)) { + break; + } + } + if (*p == NUL) { + break; + } + } + } + rettv->vval.v_string = vim_strnsave(head, (int)(tail - head)); +} + /* * "type(expr)" function */ diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua index 801d2cc468..23959f348a 100644 --- a/src/nvim/eval.lua +++ b/src/nvim/eval.lua @@ -323,6 +323,7 @@ return { tolower={args=1}, toupper={args=1}, tr={args=3}, + trim={args={1,2}}, trunc={args=1, func="float_op_wrapper", data="&trunc"}, type={args=1}, undofile={args=1}, diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c index 78fac5acf8..8b650d0d5b 100644 --- a/src/nvim/fileio.c +++ b/src/nvim/fileio.c @@ -4892,10 +4892,12 @@ buf_check_timestamp ( )) { retval = 1; - /* set b_mtime to stop further warnings (e.g., when executing - * FileChangedShell autocmd) */ + // set b_mtime to stop further warnings (e.g., when executing + // FileChangedShell autocmd) if (!file_info_ok) { - buf->b_mtime = 0; + // When 'autoread' is set we'll check the file again to see if it + // re-appears. + buf->b_mtime = buf->b_p_ar; buf->b_orig_size = 0; buf->b_orig_mode = 0; } else { diff --git a/src/nvim/mbyte.c b/src/nvim/mbyte.c index 15fe51cad1..94bf7fb985 100644 --- a/src/nvim/mbyte.c +++ b/src/nvim/mbyte.c @@ -1829,8 +1829,8 @@ const char *mb_unescape(const char **const pp) */ bool mb_lefthalve(int row, int col) { - return (*mb_off2cells)(LineOffset[row] + col, - LineOffset[row] + screen_Columns) > 1; + return utf_off2cells(LineOffset[row] + col, + LineOffset[row] + screen_Columns) > 1; } /* diff --git a/src/nvim/mbyte.h b/src/nvim/mbyte.h index a21c08c7fe..5f48e1783e 100644 --- a/src/nvim/mbyte.h +++ b/src/nvim/mbyte.h @@ -53,7 +53,6 @@ enum { MAX_MCO = 6 }; #define mb_ptr2cells utf_ptr2cells #define mb_ptr2cells_len utf_ptr2cells_len #define mb_char2cells utf_char2cells -#define mb_off2cells utf_off2cells #define mb_head_off utf_head_off /// Flags for vimconv_T diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index 4308c4e87e..a19e98725a 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -4541,11 +4541,6 @@ void ex_cbuffer(exarg_T *eap) qf_info_T *qi = &ql_info; const char *au_name = NULL; - if (eap->cmdidx == CMD_lbuffer || eap->cmdidx == CMD_lgetbuffer - || eap->cmdidx == CMD_laddbuffer) { - qi = ll_get_or_alloc_list(curwin); - } - switch (eap->cmdidx) { case CMD_cbuffer: au_name = "cbuffer"; @@ -4576,6 +4571,13 @@ void ex_cbuffer(exarg_T *eap) } } + // Must come after autocommands. + if (eap->cmdidx == CMD_lbuffer + || eap->cmdidx == CMD_lgetbuffer + || eap->cmdidx == CMD_laddbuffer) { + qi = ll_get_or_alloc_list(curwin); + } + if (*eap->arg == NUL) buf = curbuf; else if (*skipwhite(skipdigits(eap->arg)) == NUL) diff --git a/src/nvim/screen.c b/src/nvim/screen.c index bcfef89cc2..ec48bf5dcf 100644 --- a/src/nvim/screen.c +++ b/src/nvim/screen.c @@ -4232,26 +4232,19 @@ win_line ( /* Remember that the line wraps, used for modeless copy. */ LineWraps[screen_row - 1] = TRUE; - /* - * Special trick to make copy/paste of wrapped lines work with - * xterm/screen: write an extra character beyond the end of - * the line. This will work with all terminal types - * (regardless of the xn,am settings). - * Only do this if the cursor is on the current line - * (something has been written in it). - * Don't do this for double-width characters. - * Don't do this for a window not at the right screen border. - */ - if (!(has_mbyte - && ((*mb_off2cells)(LineOffset[screen_row], - LineOffset[screen_row] + screen_Columns) - == 2 - || (*mb_off2cells)(LineOffset[screen_row - 1] - + (int)Columns - 2, - LineOffset[screen_row] + screen_Columns) - == 2)) - ) { - ui_add_linewrap(screen_row-1); + // Special trick to make copy/paste of wrapped lines work with + // xterm/screen: write an extra character beyond the end of + // the line. This will work with all terminal types + // (regardless of the xn,am settings). + // Only do this if the cursor is on the current line + // (something has been written in it). + // Don't do this for double-width characters. + // Don't do this for a window not at the right screen border. + if (utf_off2cells(LineOffset[screen_row], + LineOffset[screen_row] + screen_Columns) != 2 + && utf_off2cells(LineOffset[screen_row - 1] + (int)Columns - 2, + LineOffset[screen_row] + screen_Columns) != 2) { + ui_add_linewrap(screen_row - 1); } } @@ -4304,7 +4297,7 @@ static int char_needs_redraw(int off_from, int off_to, int cols) return (cols > 0 && ((schar_cmp(ScreenLines[off_from], ScreenLines[off_to]) || ScreenAttrs[off_from] != ScreenAttrs[off_to] - || ((*mb_off2cells)(off_from, off_from + cols) > 1 + || (utf_off2cells(off_from, off_from + cols) > 1 && schar_cmp(ScreenLines[off_from + 1], ScreenLines[off_to + 1]))) || p_wd < 0)); @@ -4330,15 +4323,11 @@ static void screen_line(int row, int coloff, int endcol, unsigned max_off_to; int col = 0; int hl; - int force = FALSE; /* force update rest of the line */ - int redraw_this /* bool: does character need redraw? */ - ; - int redraw_next; /* redraw_this for next character */ - int clear_next = FALSE; - int char_cells; /* 1: normal char */ - /* 2: occupies two display cells */ -# define CHAR_CELLS char_cells - + bool redraw_this; // Does character need redraw? + bool redraw_next; // redraw_this for next character + bool clear_next = false; + int char_cells; // 1: normal char + // 2: occupies two display cells int start_dirty = -1, end_dirty = 0; /* Check for illegal row and col, just in case. */ @@ -4383,15 +4372,14 @@ static void screen_line(int row, int coloff, int endcol, redraw_next = char_needs_redraw(off_from, off_to, endcol - col); while (col < endcol) { - if (has_mbyte && (col + 1 < endcol)) - char_cells = (*mb_off2cells)(off_from, max_off_from); - else - char_cells = 1; - + char_cells = 1; + if (col + 1 < endcol) { + char_cells = utf_off2cells(off_from, max_off_from); + } redraw_this = redraw_next; - redraw_next = force || char_needs_redraw(off_from + CHAR_CELLS, - off_to + CHAR_CELLS, endcol - col - CHAR_CELLS); - + redraw_next = char_needs_redraw(off_from + char_cells, + off_to + char_cells, + endcol - col - char_cells); if (redraw_this) { if (start_dirty == -1) { @@ -4403,12 +4391,12 @@ static void screen_line(int row, int coloff, int endcol, // the right halve of the old character. // Also required when writing the right halve of a double-width // char over the left halve of an existing one - if (has_mbyte && col + char_cells == endcol + if (col + char_cells == endcol && ((char_cells == 1 - && (*mb_off2cells)(off_to, max_off_to) > 1) + && utf_off2cells(off_to, max_off_to) > 1) || (char_cells == 2 - && (*mb_off2cells)(off_to, max_off_to) == 1 - && (*mb_off2cells)(off_to + 1, max_off_to) > 1))) { + && utf_off2cells(off_to, max_off_to) == 1 + && utf_off2cells(off_to + 1, max_off_to) > 1))) { clear_next = true; } @@ -4425,9 +4413,9 @@ static void screen_line(int row, int coloff, int endcol, } } - off_to += CHAR_CELLS; - off_from += CHAR_CELLS; - col += CHAR_CELLS; + off_to += char_cells; + off_from += char_cells; + col += char_cells; } if (clear_next) { @@ -5396,15 +5384,15 @@ void screen_puts_len(char_u *text, int textlen, int row, int col, int attr) // character with a one-cell character, need to clear the next // cell. Also when overwriting the left halve of a two-cell char // with the right halve of a two-cell char. Do this only once - // (mb_off2cells() may return 2 on the right halve). + // (utf8_off2cells() may return 2 on the right halve). if (clear_next_cell) { clear_next_cell = false; } else if ((len < 0 ? ptr[mbyte_blen] == NUL : ptr + mbyte_blen >= text + len) - && ((mbyte_cells == 1 && (*mb_off2cells)(off, max_off) > 1) + && ((mbyte_cells == 1 && utf_off2cells(off, max_off) > 1) || (mbyte_cells == 2 - && (*mb_off2cells)(off, max_off) == 1 - && (*mb_off2cells)(off + 1, max_off) > 1))) { + && utf_off2cells(off, max_off) == 1 + && utf_off2cells(off + 1, max_off) > 1))) { clear_next_cell = true; } diff --git a/src/nvim/tag.c b/src/nvim/tag.c index c09a13edb1..2a980af2a2 100644 --- a/src/nvim/tag.c +++ b/src/nvim/tag.c @@ -952,12 +952,12 @@ void do_tags(exarg_T *eap) continue; msg_putchar('\n'); - sprintf((char *)IObuff, "%c%2d %2d %-15s %5ld ", - i == tagstackidx ? '>' : ' ', - i + 1, - tagstack[i].cur_match + 1, - tagstack[i].tagname, - tagstack[i].fmark.mark.lnum); + vim_snprintf((char *)IObuff, IOSIZE, "%c%2d %2d %-15s %5ld ", + i == tagstackidx ? '>' : ' ', + i + 1, + tagstack[i].cur_match + 1, + tagstack[i].tagname, + tagstack[i].fmark.mark.lnum); msg_outtrans(IObuff); msg_outtrans_attr(name, tagstack[i].fmark.fnum == curbuf->b_fnum ? HL_ATTR(HLF_D) : 0); @@ -2217,6 +2217,16 @@ static bool test_for_static(tagptrs_T *tagp) return FALSE; } +// Returns the length of a matching tag line. +static size_t matching_line_len(const char_u *const lbuf) +{ + const char_u *p = lbuf + 1; + + // does the same thing as parse_match() + p += STRLEN(p) + 1; + return (p - lbuf) + STRLEN(p); +} + /* * Parse a line from a matching tag. Does not change the line itself. * @@ -2300,11 +2310,10 @@ static char_u *tag_full_fname(tagptrs_T *tagp) * * returns OK for success, NOTAGFILE when file not found, FAIL otherwise. */ -static int -jumpto_tag ( - char_u *lbuf, /* line from the tags file for this tag */ - int forceit, /* :ta with ! */ - int keep_help /* keep help flag (FALSE for cscope) */ +static int jumpto_tag( + const char_u *lbuf_arg, // line from the tags file for this tag + int forceit, // :ta with ! + int keep_help // keep help flag (FALSE for cscope) ) { int save_secure; @@ -2312,7 +2321,6 @@ jumpto_tag ( bool save_p_ws; int save_p_scs, save_p_ic; linenr_T save_lnum; - int csave = 0; char_u *str; char_u *pbuf; /* search pattern buffer */ char_u *pbuf_end; @@ -2327,6 +2335,9 @@ jumpto_tag ( char_u *full_fname = NULL; int old_KeyTyped = KeyTyped; /* getting the file may reset it */ const int l_g_do_tagpreview = g_do_tagpreview; + const size_t len = matching_line_len(lbuf_arg) + 1; + char_u *lbuf = xmalloc(len); + memmove(lbuf, lbuf_arg, len); pbuf = xmalloc(LSIZE); @@ -2336,8 +2347,7 @@ jumpto_tag ( goto erret; } - /* truncate the file name, so it can be used as a string */ - csave = *tagp.fname_end; + // truncate the file name, so it can be used as a string *tagp.fname_end = NUL; fname = tagp.fname; @@ -2447,7 +2457,10 @@ jumpto_tag ( else keep_help_flag = curbuf->b_help; } + if (getfile_result == GETFILE_UNUSED) { + // Careful: getfile() may trigger autocommands and call jumpto_tag() + // recursively. getfile_result = getfile(0, fname, NULL, true, (linenr_T)0, forceit); } keep_help_flag = false; @@ -2605,9 +2618,8 @@ jumpto_tag ( } erret: - g_do_tagpreview = 0; /* For next time */ - if (tagp.fname_end != NULL) - *tagp.fname_end = csave; + g_do_tagpreview = 0; // For next time + xfree(lbuf); xfree(pbuf); xfree(tofree_fname); xfree(full_fname); diff --git a/src/nvim/testdir/Makefile b/src/nvim/testdir/Makefile index 361db47fc7..1e3dc04049 100644 --- a/src/nvim/testdir/Makefile +++ b/src/nvim/testdir/Makefile @@ -114,6 +114,7 @@ NEW_TESTS ?= \ test_timers.res \ test_undo.res \ test_usercommands.res \ + test_user_func.res \ test_vimscript.res \ test_visual.res \ test_winbuf_close.res \ diff --git a/src/nvim/testdir/test_alot.vim b/src/nvim/testdir/test_alot.vim index 238dbe8d90..ace4b377cb 100644 --- a/src/nvim/testdir/test_alot.vim +++ b/src/nvim/testdir/test_alot.vim @@ -19,6 +19,7 @@ source test_functions.vim source test_ga.vim source test_global.vim source test_goto.vim +source test_join.vim source test_jumps.vim source test_fileformat.vim source test_filetype.vim diff --git a/src/nvim/testdir/test_autocmd.vim b/src/nvim/testdir/test_autocmd.vim index e4ab3ccea8..b1502eff89 100644 --- a/src/nvim/testdir/test_autocmd.vim +++ b/src/nvim/testdir/test_autocmd.vim @@ -1,5 +1,7 @@ " Tests for autocommands +source shared.vim + func! s:cleanup_buffers() abort for bnr in range(1, bufnr('$')) if bufloaded(bnr) && bufnr('%') != bnr @@ -248,6 +250,23 @@ func Test_augroup_warning() au! VimEnter endfunc +func Test_BufReadCmdHelp() + " This used to cause access to free memory + au BufReadCmd * e +h + help + + au! BufReadCmd +endfunc + +func Test_BufReadCmdHelpJump() + " This used to cause access to free memory + au BufReadCmd * e +h{ + " } to fix highlighting + call assert_fails('help', 'E434:') + + au! BufReadCmd +endfunc + func Test_augroup_deleted() " This caused a crash before E936 was introduced augroup x @@ -1165,6 +1184,13 @@ func Test_nocatch_wipe_dummy_buffer() au! endfunc +func Test_wipe_cbuffer() + sv x + au * * bw + lb + au! +endfunc + " Test TextChangedI and TextChangedP func Test_ChangedP() " Nvim does not support test_override(). @@ -1245,3 +1271,22 @@ func Test_TextChangedI_with_setline() call test_override('starting', 0) bwipe! endfunc + +func Test_Changed_FirstTime() + if !has('terminal') || has('gui_running') + return + endif + " Prepare file for TextChanged event. + call writefile([''], 'Xchanged.txt') + let buf = term_start([GetVimProg(), '--clean', '-c', 'set noswapfile'], {'term_rows': 3}) + call assert_equal('running', term_getstatus(buf)) + " It's only adding autocmd, so that no event occurs. + call term_sendkeys(buf, ":au! TextChanged <buffer> call writefile(['No'], 'Xchanged.txt')\<cr>") + call term_sendkeys(buf, "\<C-\\>\<C-N>:qa!\<cr>") + call WaitFor({-> term_getstatus(buf) == 'finished'}) + call assert_equal([''], readfile('Xchanged.txt')) + + " clean up + call delete('Xchanged.txt') + bwipe! +endfunc diff --git a/src/nvim/testdir/test_functions.vim b/src/nvim/testdir/test_functions.vim index 6d0a6b9d5e..e2a035b0b2 100644 --- a/src/nvim/testdir/test_functions.vim +++ b/src/nvim/testdir/test_functions.vim @@ -926,3 +926,26 @@ func Test_redo_in_nested_functions() delfunc Operator delfunc Apply endfunc + +func Test_trim() + call assert_equal("Testing", trim(" \t\r\r\x0BTesting \t\n\r\n\t\x0B\x0B")) + call assert_equal("Testing", trim(" \t \r\r\n\n\x0BTesting \t\n\r\n\t\x0B\x0B")) + call assert_equal("RESERVE", trim("xyz \twwRESERVEzyww \t\t", " wxyz\t")) + call assert_equal("wRE \tSERVEzyww", trim("wRE \tSERVEzyww")) + call assert_equal("abcd\t xxxx tail", trim(" \tabcd\t xxxx tail")) + call assert_equal("\tabcd\t xxxx tail", trim(" \tabcd\t xxxx tail", " ")) + call assert_equal(" \tabcd\t xxxx tail", trim(" \tabcd\t xxxx tail", "abx")) + call assert_equal("RESERVE", trim("你RESERVE好", "你好")) + call assert_equal("您R E SER V E早", trim("你好您R E SER V E早好你你", "你好")) + call assert_equal("你好您R E SER V E早好你你", trim(" \n\r\r 你好您R E SER V E早好你你 \t \x0B", )) + call assert_equal("您R E SER V E早好你你 \t \x0B", trim(" 你好您R E SER V E早好你你 \t \x0B", " 你好")) + call assert_equal("您R E SER V E早好你你 \t \x0B", trim(" tteesstttt你好您R E SER V E早好你你 \t \x0B ttestt", " 你好tes")) + call assert_equal("您R E SER V E早好你你 \t \x0B", trim(" tteesstttt你好您R E SER V E早好你你 \t \x0B ttestt", " 你你你好好好tttsses")) + call assert_equal("留下", trim("这些些不要这些留下这些", "这些不要")) + call assert_equal("", trim("", "")) + call assert_equal("a", trim("a", "")) + call assert_equal("", trim("", "a")) + + let chars = join(map(range(1, 0x20) + [0xa0], {n -> nr2char(n)}), '') + call assert_equal("x", trim(chars . "x" . chars)) +endfunc diff --git a/src/nvim/testdir/test_join.vim b/src/nvim/testdir/test_join.vim new file mode 100644 index 0000000000..1c97414164 --- /dev/null +++ b/src/nvim/testdir/test_join.vim @@ -0,0 +1,35 @@ +" Test for joining lines. + +func Test_join_with_count() + new + call setline(1, ['one', 'two', 'three', 'four']) + normal J + call assert_equal('one two', getline(1)) + %del + call setline(1, ['one', 'two', 'three', 'four']) + normal 10J + call assert_equal('one two three four', getline(1)) + quit! +endfunc + +" Tests for setting the '[,'] marks when joining lines. +func Test_join_marks() + enew + call append(0, [ + \ "\t\tO sodales, ludite, vos qui", + \ "attamen consulite per voster honur. Tua pulchra " . + \ "facies me fay planszer milies", + \ "", + \ "This line.", + \ "Should be joined with the next line", + \ "and with this line"]) + + normal gg0gqj + call assert_equal([0, 1, 1, 0], getpos("'[")) + call assert_equal([0, 2, 1, 0], getpos("']")) + + /^This line/;'}-join + call assert_equal([0, 4, 11, 0], getpos("'[")) + call assert_equal([0, 4, 67, 0], getpos("']")) + enew! +endfunc diff --git a/src/nvim/testdir/test_stat.vim b/src/nvim/testdir/test_stat.vim index 0a09130b0c..c276df0a92 100644 --- a/src/nvim/testdir/test_stat.vim +++ b/src/nvim/testdir/test_stat.vim @@ -43,7 +43,16 @@ func Test_existent_directory() call assert_equal(0, getfsize(dname)) call assert_equal('dir', getftype(dname)) - call assert_equal('rwx', getfperm(dname)[0:2]) + call assert_equal(has('win32') ? 'rw-' : 'rwx', getfperm(dname)[0:2]) +endfunc + +func SleepForTimestamp() + " FAT has a granularity of 2 seconds, otherwise it's usually 1 second + if has('win32') + sleep 2 + else + sleep 2 + endif endfunc func Test_checktime() @@ -53,12 +62,7 @@ func Test_checktime() call writefile(fl, fname) set autoread exec 'e' fname - " FAT has a granularity of 2 seconds, otherwise it's usually 1 second - if has('win32') - sleep 2 - else - sleep 2 - endif + call SleepForTimestamp() let fl = readfile(fname) let fl[0] .= ' - checktime' call writefile(fl, fname) @@ -68,6 +72,46 @@ func Test_checktime() call delete(fname) endfunc +func Test_autoread_file_deleted() + new Xautoread + set autoread + call setline(1, 'original') + w! + + call SleepForTimestamp() + if has('win32') + silent !echo changed > Xautoread + else + silent !echo 'changed' > Xautoread + endif + checktime + call assert_equal('changed', trim(getline(1))) + + call SleepForTimestamp() + messages clear + if has('win32') + silent !del Xautoread + else + silent !rm Xautoread + endif + checktime + call assert_match('E211:', execute('messages')) + call assert_equal('changed', trim(getline(1))) + + call SleepForTimestamp() + if has('win32') + silent !echo recreated > Xautoread + else + silent !echo 'recreated' > Xautoread + endif + checktime + call assert_equal('recreated', trim(getline(1))) + + call delete('Xautoread') + bwipe! +endfunc + + func Test_nonexistent_file() let fname = 'Xtest.tmp' @@ -78,6 +122,41 @@ func Test_nonexistent_file() call assert_equal('', getfperm(fname)) endfunc +func Test_getftype() + call assert_equal('file', getftype(v:progpath)) + call assert_equal('dir', getftype('.')) + + if !has('unix') + return + endif + + silent !ln -s Xfile Xlink + call assert_equal('link', getftype('Xlink')) + call delete('Xlink') + + if executable('mkfifo') + silent !mkfifo Xfifo + call assert_equal('fifo', getftype('Xfifo')) + call delete('Xfifo') + endif + + for cdevfile in systemlist('find /dev -type c -maxdepth 2 2>/dev/null') + call assert_equal('cdev', getftype(cdevfile)) + endfor + + for bdevfile in systemlist('find /dev -type b -maxdepth 2 2>/dev/null') + call assert_equal('bdev', getftype(bdevfile)) + endfor + + " The /run/ directory typically contains socket files. + " If it does not, test won't fail but will not test socket files. + for socketfile in systemlist('find /run -type s -maxdepth 2 2>/dev/null') + call assert_equal('socket', getftype(socketfile)) + endfor + + " TODO: file type 'other' is not tested. How can we test it? +endfunc + func Test_win32_symlink_dir() " On Windows, non-admin users cannot create symlinks. " So we use an existing symlink for this test. diff --git a/src/nvim/testdir/test_tagjump.vim b/src/nvim/testdir/test_tagjump.vim index 268a153077..f9bd8b5246 100644 --- a/src/nvim/testdir/test_tagjump.vim +++ b/src/nvim/testdir/test_tagjump.vim @@ -230,4 +230,32 @@ func Test_tag_file_encoding() call delete('Xtags1') endfunc +func Test_tagjump_etags() + if !has('emacs_tags') + return + endif + call writefile([ + \ "void foo() {}", + \ "int main(int argc, char **argv)", + \ "{", + \ "\tfoo();", + \ "\treturn 0;", + \ "}", + \ ], 'Xmain.c') + + call writefile([ + \ "\x0c", + \ "Xmain.c,64", + \ "void foo() {}\x7ffoo\x011,0", + \ "int main(int argc, char **argv)\x7fmain\x012,14", + \ ], 'Xtags') + set tags=Xtags + ta foo + call assert_equal('void foo() {}', getline('.')) + + call delete('Xtags') + call delete('Xmain.c') + bwipe! +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_taglist.vim b/src/nvim/testdir/test_taglist.vim index 2d1557ebd9..3ad2025915 100644 --- a/src/nvim/testdir/test_taglist.vim +++ b/src/nvim/testdir/test_taglist.vim @@ -1,4 +1,4 @@ -" test 'taglist' function +" test 'taglist' function and :tags command func Test_taglist() call writefile([ @@ -56,3 +56,8 @@ func Test_taglist_ctags_etags() call delete('Xtags') endfunc + +func Test_tags_too_long() + call assert_fails('tag ' . repeat('x', 1020), 'E426') + tags +endfunc diff --git a/src/nvim/testdir/test_user_func.vim b/src/nvim/testdir/test_user_func.vim new file mode 100644 index 0000000000..e7a3701386 --- /dev/null +++ b/src/nvim/testdir/test_user_func.vim @@ -0,0 +1,96 @@ +" Test for user functions. +" Also test an <expr> mapping calling a function. +" Also test that a builtin function cannot be replaced. +" Also test for regression when calling arbitrary expression. + +func Table(title, ...) + let ret = a:title + let idx = 1 + while idx <= a:0 + exe "let ret = ret . a:" . idx + let idx = idx + 1 + endwhile + return ret +endfunc + +func Compute(n1, n2, divname) + if a:n2 == 0 + return "fail" + endif + exe "let g:" . a:divname . " = ". a:n1 / a:n2 + return "ok" +endfunc + +func Expr1() + silent! normal! v + return "111" +endfunc + +func Expr2() + call search('XX', 'b') + return "222" +endfunc + +func ListItem() + let g:counter += 1 + return g:counter . '. ' +endfunc + +func ListReset() + let g:counter = 0 + return '' +endfunc + +func FuncWithRef(a) + unlet g:FuncRef + return a:a +endfunc + +func Test_user_func() + let g:FuncRef=function("FuncWithRef") + let g:counter = 0 + inoremap <expr> ( ListItem() + inoremap <expr> [ ListReset() + imap <expr> + Expr1() + imap <expr> * Expr2() + let g:retval = "nop" + + call assert_equal('xxx4asdf', Table("xxx", 4, "asdf")) + call assert_equal('fail', Compute(45, 0, "retval")) + call assert_equal('nop', g:retval) + call assert_equal('ok', Compute(45, 5, "retval")) + call assert_equal(9, g:retval) + call assert_equal(333, g:FuncRef(333)) + + enew + + normal oXX+-XX + call assert_equal('XX111-XX', getline('.')) + normal o---*--- + call assert_equal('---222---', getline('.')) + normal o(one + call assert_equal('1. one', getline('.')) + normal o(two + call assert_equal('2. two', getline('.')) + normal o[(one again + call assert_equal('1. one again', getline('.')) + + call assert_equal(3, max([1, 2, 3])) + call assert_fails("call extend(g:, {'max': function('min')})", 'E704') + call assert_equal(3, max([1, 2, 3])) + + " Regression: the first line below used to throw ?E110: Missing ')'? + " Second is here just to prove that this line is correct when not skipping + " rhs of &&. + call assert_equal(0, (0 && (function('tr'))(1, 2, 3))) + call assert_equal(1, (1 && (function('tr'))(1, 2, 3))) + + delfunc Table + delfunc Compute + delfunc Expr1 + delfunc Expr2 + delfunc ListItem + delfunc ListReset + unlet g:retval g:counter + enew! +endfunc |