diff options
-rw-r--r-- | src/nvim/buffer.c | 2 | ||||
-rw-r--r-- | src/nvim/eval.c | 13 | ||||
-rw-r--r-- | src/nvim/globals.h | 4 | ||||
-rw-r--r-- | src/nvim/mark.c | 2 | ||||
-rw-r--r-- | src/nvim/normal.c | 2 | ||||
-rw-r--r-- | src/nvim/pos.h | 1 | ||||
-rw-r--r-- | src/nvim/regexp.c | 73 | ||||
-rw-r--r-- | src/nvim/regexp_nfa.c | 8 | ||||
-rw-r--r-- | src/nvim/search.c | 2 | ||||
-rw-r--r-- | src/nvim/tag.c | 2 | ||||
-rw-r--r-- | src/nvim/testdir/test_functions.vim | 8 | ||||
-rw-r--r-- | src/nvim/testdir/test_true_false.vim | 5 | ||||
-rw-r--r-- | src/nvim/testdir/test_visual.vim | 103 |
13 files changed, 166 insertions, 59 deletions
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index 6e4e7afeb2..8cb4e32815 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -2446,7 +2446,7 @@ void get_winopts(buf_T *buf) */ pos_T *buflist_findfpos(buf_T *buf) { - static pos_T no_position = INIT_POS_T(1, 0, 0); + static pos_T no_position = { 1, 0, 0 }; wininfo_T *wip = find_wininfo(buf, FALSE); return (wip == NULL) ? &no_position : &(wip->wi_fpos); diff --git a/src/nvim/eval.c b/src/nvim/eval.c index aa0d925ff2..57777f049a 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -10086,10 +10086,23 @@ static void getpos_both(typval_T *argvars, typval_T *rettv, bool getcurpos) tv_list_append_number( l, (fp != NULL) ? (varnumber_T)fp->coladd : (varnumber_T)0); if (getcurpos) { + const int save_set_curswant = curwin->w_set_curswant; + const colnr_T save_curswant = curwin->w_curswant; + const colnr_T save_virtcol = curwin->w_virtcol; + update_curswant(); tv_list_append_number(l, (curwin->w_curswant == MAXCOL ? (varnumber_T)MAXCOL : (varnumber_T)curwin->w_curswant + 1)); + + // Do not change "curswant", as it is unexpected that a get + // function has a side effect. + if (save_set_curswant) { + curwin->w_set_curswant = save_set_curswant; + curwin->w_curswant = save_curswant; + curwin->w_virtcol = save_virtcol; + curwin->w_valid &= ~VALID_VIRTCOL; + } } } diff --git a/src/nvim/globals.h b/src/nvim/globals.h index 52c5d65512..004b3252da 100644 --- a/src/nvim/globals.h +++ b/src/nvim/globals.h @@ -602,7 +602,7 @@ EXTERN bool can_si INIT(= false); EXTERN bool can_si_back INIT(= false); // w_cursor before formatting text. -EXTERN pos_T saved_cursor INIT(= INIT_POS_T(0, 0, 0)); +EXTERN pos_T saved_cursor INIT(= { 0, 0, 0 }); /* * Stuff for insert mode. @@ -789,7 +789,7 @@ EXTERN int autocmd_bufnr INIT(= 0); // fnum for <abuf> on cmdline EXTERN char_u *autocmd_match INIT(= NULL); // name for <amatch> on cmdline EXTERN int did_cursorhold INIT(= false); // set when CursorHold t'gerd // for CursorMoved event -EXTERN pos_T last_cursormoved INIT(= INIT_POS_T(0, 0, 0)); +EXTERN pos_T last_cursormoved INIT(= { 0, 0, 0 }); EXTERN int postponed_split INIT(= 0); /* for CTRL-W CTRL-] command */ EXTERN int postponed_split_flags INIT(= 0); /* args for win_split() */ diff --git a/src/nvim/mark.c b/src/nvim/mark.c index 05f78c76bc..602648c27c 100644 --- a/src/nvim/mark.c +++ b/src/nvim/mark.c @@ -924,7 +924,7 @@ static void mark_adjust_internal(linenr_T line1, linenr_T line2, int i; int fnum = curbuf->b_fnum; linenr_T *lp; - static pos_T initpos = INIT_POS_T(1, 0, 0); + static pos_T initpos = { 1, 0, 0 }; if (line2 < line1 && amount_after == 0L) /* nothing to do */ return; diff --git a/src/nvim/normal.c b/src/nvim/normal.c index 0b85714e39..f12abd362f 100644 --- a/src/nvim/normal.c +++ b/src/nvim/normal.c @@ -5444,7 +5444,7 @@ static void nv_csearch(cmdarg_T *cap) */ static void nv_brackets(cmdarg_T *cap) { - pos_T new_pos = INIT_POS_T(0, 0, 0); + pos_T new_pos = { 0, 0, 0 }; pos_T prev_pos; pos_T *pos = NULL; /* init for GCC */ pos_T old_pos; /* cursor position before command */ diff --git a/src/nvim/pos.h b/src/nvim/pos.h index 0a2afd5847..47d253e083 100644 --- a/src/nvim/pos.h +++ b/src/nvim/pos.h @@ -24,7 +24,6 @@ typedef struct { colnr_T coladd; } pos_T; -# define INIT_POS_T(l, c, ca) {l, c, ca} /* * Same, but without coladd. diff --git a/src/nvim/regexp.c b/src/nvim/regexp.c index 55490446e5..ab1a7c7b3e 100644 --- a/src/nvim/regexp.c +++ b/src/nvim/regexp.c @@ -1210,13 +1210,10 @@ char_u *skip_regexp(char_u *startp, int dirc, int magic, char_u **newp) return p; } -/// /// Return TRUE if the back reference is legal. We must have seen the close /// brace. -/// TODO(billy4195): Should also check that we don't refer to something that is -/// repeated +/// TODO(vim): Should also check that we don't refer to something repeated /// (+*=): what instance of the repetition should we match? -/// static int seen_endbrace(int refnum) { if (!had_endbrace[refnum]) { @@ -3388,17 +3385,13 @@ static long bt_regexec_multi(regmmatch_T *rmp, win_T *win, buf_T *buf, return bt_regexec_both(NULL, col, tm, timed_out); } -/* - * Match a regexp against a string ("line" points to the string) or multiple - * lines ("line" is NULL, use reg_getline()). - * Returns 0 for failure, number of lines contained in the match otherwise. - */ +/// Match a regexp against a string ("line" points to the string) or multiple +/// lines ("line" is NULL, use reg_getline()). +/// @return 0 for failure, or number of lines contained in the match. static long bt_regexec_both(char_u *line, - // column to start looking for match - colnr_T col, + colnr_T col, // column to start search proftime_T *tm, // timeout limit or NULL - int *timed_out // flag set on timeout or NULL - ) + int *timed_out) // flag set on timeout or NULL { bt_regprog_T *prog; char_u *s; @@ -3604,12 +3597,12 @@ void unref_extmatch(reg_extmatch_T *em) } } -/* - * regtry - try match of "prog" with at regline["col"]. - * Returns 0 for failure, number of lines contained in the match otherwise. - */ -static long regtry(bt_regprog_T *prog, colnr_T col, - proftime_T *tm, int *timed_out) +/// Try match of "prog" with at regline["col"]. +/// @returns 0 for failure, or number of lines contained in the match. +static long regtry(bt_regprog_T *prog, + colnr_T col, + proftime_T *tm, // timeout limit or NULL + int *timed_out) // flag set on timeout or NULL { reginput = regline + col; need_clear_subexpr = TRUE; @@ -3760,26 +3753,23 @@ static int reg_match_visual(void) static long bl_minval; static long bl_maxval; -/* - * regmatch - main matching routine - * - * Conceptually the strategy is simple: Check to see whether the current node - * matches, push an item onto the regstack and loop to see whether the rest - * matches, and then act accordingly. In practice we make some effort to - * avoid using the regstack, in particular by going through "ordinary" nodes - * (that don't need to know whether the rest of the match failed) by a nested - * loop. - * - * Returns TRUE when there is a match. Leaves reginput and reglnum just after - * the last matched character. - * Returns FALSE when there is no match. Leaves reginput and reglnum in an - * undefined state! - */ -static int -regmatch( +/// Main matching routine +/// +/// Conceptually the strategy is simple: Check to see whether the current node +/// matches, push an item onto the regstack and loop to see whether the rest +/// matches, and then act accordingly. In practice we make some effort to +/// avoid using the regstack, in particular by going through "ordinary" nodes +/// (that don't need to know whether the rest of the match failed) by a nested +/// loop. +/// +/// Returns TRUE when there is a match. Leaves reginput and reglnum just after +/// the last matched character. +/// Returns FALSE when there is no match. Leaves reginput and reglnum in an +/// undefined state! +static int regmatch( char_u *scan, // Current node. - proftime_T *tm, - int *timed_out + proftime_T *tm, // timeout limit or NULL + int *timed_out // flag set on timeout or NULL ) { char_u *next; /* Next node. */ @@ -3788,14 +3778,13 @@ regmatch( regitem_T *rp; int no; int status; // one of the RA_ values: - int tm_count; // counter for checking timeout + int tm_count = 0; #define RA_FAIL 1 // something failed, abort #define RA_CONT 2 // continue in inner loop #define RA_BREAK 3 // break inner loop #define RA_MATCH 4 // successful match #define RA_NOMATCH 5 // didn't match - tm_count = 0; // Make "regstack" and "backpos" empty. They are allocated and freed in // bt_regexec_both() to reduce malloc()/free() calls. regstack.ga_len = 0; @@ -3825,9 +3814,13 @@ regmatch( status = RA_FAIL; break; } + // Check for timeout once in a 100 times to avoid overhead. if (tm != NULL && ++tm_count == 100) { tm_count = 0; if (profile_passed_limit(*tm)) { + if (timed_out != NULL) { + *timed_out = true; + } status = RA_FAIL; break; } diff --git a/src/nvim/regexp_nfa.c b/src/nvim/regexp_nfa.c index e7ea036a3b..e0e8820b87 100644 --- a/src/nvim/regexp_nfa.c +++ b/src/nvim/regexp_nfa.c @@ -6276,8 +6276,10 @@ theend: // Try match of "prog" with at regline["col"]. // Returns <= 0 for failure, number of lines contained in the match otherwise. -static long nfa_regtry(nfa_regprog_T *prog, colnr_T col, - proftime_T *tm, int *timed_out) +static long nfa_regtry(nfa_regprog_T *prog, + colnr_T col, + proftime_T *tm, // timeout limit or NULL + int *timed_out) // flag set on timeout or NULL { int i; regsubs_T subs, m; @@ -6397,6 +6399,7 @@ static long nfa_regtry(nfa_regprog_T *prog, colnr_T col, /// @param line String in which to search or NULL /// @param startcol Column to start looking for match /// @param tm Timeout limit or NULL +/// @param timed_out Flag set on timeout or NULL /// /// @return <= 0 if there is no match and number of lines contained in the /// match otherwise. @@ -6642,6 +6645,7 @@ nfa_regexec_nl ( /// @param lnum Number of line to start looking for match /// @param col Column to start looking for match /// @param tm Timeout limit or NULL +/// @param timed_out Flag set on timeout or NULL /// /// @return <= 0 if there is no match and number of lines contained in the match /// otherwise. diff --git a/src/nvim/search.c b/src/nvim/search.c index 3d95ad0e92..777ea07a21 100644 --- a/src/nvim/search.c +++ b/src/nvim/search.c @@ -526,7 +526,7 @@ int searchit( int pat_use, // which pattern to use when "pat" is empty linenr_T stop_lnum, // stop after this line number when != 0 proftime_T *tm, // timeout limit or NULL - int *timed_out // set when timed out or NULL + int *timed_out // set when timed out or NULL ) { int found; diff --git a/src/nvim/tag.c b/src/nvim/tag.c index bd837a531d..410b9dfcbd 100644 --- a/src/nvim/tag.c +++ b/src/nvim/tag.c @@ -109,7 +109,7 @@ static char_u *tagmatchname = NULL; /* name of last used tag */ * Tag for preview window is remembered separately, to avoid messing up the * normal tagstack. */ -static taggy_T ptag_entry = {NULL, {INIT_POS_T(0, 0, 0), 0, 0, NULL}, 0, 0}; +static taggy_T ptag_entry = { NULL, { { 0, 0, 0 }, 0, 0, NULL }, 0, 0 }; /* * Jump to tag; handling of tag commands and tag stack diff --git a/src/nvim/testdir/test_functions.vim b/src/nvim/testdir/test_functions.vim index bfe13d6b2d..824baffbc9 100644 --- a/src/nvim/testdir/test_functions.vim +++ b/src/nvim/testdir/test_functions.vim @@ -956,8 +956,8 @@ func Test_balloon_show() endfunc func Test_shellescape() - let save_shell = &shell - set shell=bash + let [save_shell, save_shellslash] = [&shell, &shellslash] + set shell=bash shellslash call assert_equal("'text'", shellescape('text')) call assert_equal("'te\"xt'", shellescape('te"xt')) call assert_equal("'te'\\''xt'", shellescape("te'xt")) @@ -971,13 +971,13 @@ func Test_shellescape() call assert_equal("'te\nxt'", shellescape("te\nxt")) call assert_equal("'te\\\nxt'", shellescape("te\nxt", 1)) - set shell=tcsh + set shell=tcsh shellslash call assert_equal("'te\\!xt'", shellescape("te!xt")) call assert_equal("'te\\\\!xt'", shellescape("te!xt", 1)) call assert_equal("'te\\\nxt'", shellescape("te\nxt")) call assert_equal("'te\\\\\nxt'", shellescape("te\nxt", 1)) - let &shell = save_shell + let [&shell, &shellslash] = [save_shell, save_shellslash] endfunc func Test_redo_in_nested_functions() diff --git a/src/nvim/testdir/test_true_false.vim b/src/nvim/testdir/test_true_false.vim index 84aca737ac..4a5d47471d 100644 --- a/src/nvim/testdir/test_true_false.vim +++ b/src/nvim/testdir/test_true_false.vim @@ -57,6 +57,9 @@ endfunc " Test using TRUE or FALSE values for an argument. func Test_true_false_arg() + let shellslash = &shellslash + let wildignore = &wildignore + set shellslash call Try_arg_true_false('count(["a", "A"], "a", %v%)', 1, 2) set wildignore=*.swp @@ -110,6 +113,8 @@ func Test_true_false_arg() let here_id = synID(1, 3, 0) call Try_arg_true_false('synID(1, 3, %v%)', here_id, brackets_id) bwipe! + let &wildignore = wildignore + let &shellslash = shellslash endfunc function Try_arg_non_zero(expr, false_val, true_val) diff --git a/src/nvim/testdir/test_visual.vim b/src/nvim/testdir/test_visual.vim index 4a143d665d..74afc72f03 100644 --- a/src/nvim/testdir/test_visual.vim +++ b/src/nvim/testdir/test_visual.vim @@ -1,8 +1,4 @@ " Tests for various Visual mode. -if !has('visual') - finish -endif - func Test_block_shift_multibyte() " Uses double-wide character. @@ -278,9 +274,46 @@ func Test_visual_mode_reset() set belloff& endfunc +func Test_Visual_word_textobject() + new + call setline(1, ['First sentence. Second sentence.']) + + " When start and end of visual area are identical, 'aw' or 'iw' select + " the whole word. + norm! 1go2fcvawy + call assert_equal('Second ', @") + norm! 1go2fcviwy + call assert_equal('Second', @") + + " When start and end of visual area are not identical, 'aw' or 'iw' + " extend the word in direction of the end of the visual area. + norm! 1go2fcvlawy + call assert_equal('cond ', @") + norm! gv2awy + call assert_equal('cond sentence.', @") + + norm! 1go2fcvliwy + call assert_equal('cond', @") + norm! gv2iwy + call assert_equal('cond sentence', @") + + " Extend visual area in opposite direction. + norm! 1go2fcvhawy + call assert_equal(' Sec', @") + norm! gv2awy + call assert_equal(' sentence. Sec', @") + + norm! 1go2fcvhiwy + call assert_equal('Sec', @") + norm! gv2iwy + call assert_equal('. Sec', @") + + bwipe! +endfunc + func Test_Visual_sentence_textobject() new - call setline(1, ['First sentence. Second sentence. Third', 'sentence. Fouth sentence']) + call setline(1, ['First sentence. Second sentence. Third', 'sentence. Fourth sentence']) " When start and end of visual area are identical, 'as' or 'is' select " the whole sentence. @@ -318,3 +351,63 @@ func Test_Visual_sentence_textobject() bwipe! endfunc + +func Test_curswant_not_changed() + new + call setline(1, ['one', 'two']) + au InsertLeave * call getcurpos() + call feedkeys("gg0\<C-V>jI123 \<Esc>j", 'xt') + call assert_equal([0, 2, 1, 0, 1], getcurpos()) + + bwipe! + au! InsertLeave +endfunc + +func Test_Visual_paragraph_textobject() + new + call setline(1, ['First line.', + \ '', + \ 'Second line.', + \ 'Third line.', + \ 'Fourth line.', + \ 'Fifth line.', + \ '', + \ 'Sixth line.']) + + " When start and end of visual area are identical, 'ap' or 'ip' select + " the whole paragraph. + norm! 4ggvapy + call assert_equal("Second line.\nThird line.\nFourth line.\nFifth line.\n\n", @") + norm! 4ggvipy + call assert_equal("Second line.\nThird line.\nFourth line.\nFifth line.\n", @") + + " When start and end of visual area are not identical, 'ap' or 'ip' + " extend the sentence in direction of the end of the visual area. + " FIXME: actually, it is not sufficient to have different start and + " end of visual selection, the start line and end line have to differ, + " which is not consistent with the documentation. + norm! 4ggVjapy + call assert_equal("Third line.\nFourth line.\nFifth line.\n\n", @") + norm! gvapy + call assert_equal("Third line.\nFourth line.\nFifth line.\n\nSixth line.\n", @") + norm! 4ggVjipy + call assert_equal("Third line.\nFourth line.\nFifth line.\n", @") + norm! gvipy + call assert_equal("Third line.\nFourth line.\nFifth line.\n\n", @") + norm! gvipy + call assert_equal("Third line.\nFourth line.\nFifth line.\n\nSixth line.\n", @") + + " Extend visual area in opposite direction. + norm! 5ggVkapy + call assert_equal("\nSecond line.\nThird line.\nFourth line.\n", @") + norm! gvapy + call assert_equal("First line.\n\nSecond line.\nThird line.\nFourth line.\n", @") + norm! 5ggVkipy + call assert_equal("Second line.\nThird line.\nFourth line.\n", @") + norma gvipy + call assert_equal("\nSecond line.\nThird line.\nFourth line.\n", @") + norm! gvipy + call assert_equal("First line.\n\nSecond line.\nThird line.\nFourth line.\n", @") + + bwipe! +endfunc |