diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/buffer.c | 5 | ||||
-rw-r--r-- | src/nvim/ex_cmds2.c | 9 | ||||
-rw-r--r-- | src/nvim/ex_docmd.c | 111 | ||||
-rw-r--r-- | src/nvim/ex_getln.c | 15 | ||||
-rw-r--r-- | src/nvim/normal.c | 158 | ||||
-rw-r--r-- | src/nvim/ops.c | 96 | ||||
-rw-r--r-- | src/nvim/testdir/test_cmdline.vim | 71 | ||||
-rw-r--r-- | src/nvim/testdir/test_normal.vim | 45 | ||||
-rw-r--r-- | src/nvim/vim.h | 2 |
9 files changed, 351 insertions, 161 deletions
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index 00d472b4c8..64569c294b 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -2659,9 +2659,8 @@ buf_T *setaltfname(char_u *ffname, char_u *sfname, linenr_T lnum) * Get alternate file name for current window. * Return NULL if there isn't any, and give error message if requested. */ -char_u * -getaltfname ( - int errmsg /* give error message */ +char_u * getaltfname( + bool errmsg // give error message ) { char_u *fname; diff --git a/src/nvim/ex_cmds2.c b/src/nvim/ex_cmds2.c index 120278d3fb..c384d253b9 100644 --- a/src/nvim/ex_cmds2.c +++ b/src/nvim/ex_cmds2.c @@ -2254,6 +2254,15 @@ static int alist_add_list(int count, char_u **files, int after) } } +// Function given to ExpandGeneric() to obtain the possible arguments of the +// argedit and argdelete commands. +char_u *get_arglist_name(expand_T *xp FUNC_ATTR_UNUSED, int idx) +{ + if (idx >= ARGCOUNT) { + return NULL; + } + return alist_name(&ARGLIST[idx]); +} /// ":compiler[!] {name}" void ex_compiler(exarg_T *eap) diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index c31242f2ac..20c188ed55 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -2665,8 +2665,8 @@ const char * set_one_cmd_context( size_t len = 0; exarg_T ea; int context = EXPAND_NOTHING; - int forceit = false; - int usefilter = false; // Filter instead of file name. + bool forceit = false; + bool usefilter = false; // Filter instead of file name. ExpandInit(xp); xp->xp_pattern = (char_u *)buff; @@ -2786,9 +2786,9 @@ const char * set_one_cmd_context( xp->xp_context = EXPAND_NOTHING; /* Default now that we're past command */ - if (*p == '!') { /* forced commands */ - forceit = TRUE; - ++p; + if (*p == '!') { // forced commands + forceit = true; + p++; } /* @@ -2813,10 +2813,10 @@ const char * set_one_cmd_context( } if (ea.cmdidx == CMD_read) { - usefilter = forceit; /* :r! filter if forced */ - if (*arg == '!') { /* :r !filter */ - ++arg; - usefilter = TRUE; + usefilter = forceit; // :r! filter if forced + if (*arg == '!') { // :r !filter + arg++; + usefilter = true; } } @@ -2978,7 +2978,7 @@ const char * set_one_cmd_context( // A full match ~user<Tab> will be replaced by user's home // directory i.e. something like ~user<Tab> -> /home/user/ if (*p == NUL && p > (const char *)xp->xp_pattern + 1 - && match_user(xp->xp_pattern + 1) == 1) { + && match_user(xp->xp_pattern + 1) >= 1) { xp->xp_context = EXPAND_USER; ++xp->xp_pattern; } @@ -3350,6 +3350,19 @@ const char * set_one_cmd_context( case CMD_xunmap: return (const char *)set_context_in_map_cmd( xp, (char_u *)cmd, (char_u *)arg, forceit, false, true, ea.cmdidx); + case CMD_mapclear: + case CMD_nmapclear: + case CMD_vmapclear: + case CMD_omapclear: + case CMD_imapclear: + case CMD_cmapclear: + case CMD_lmapclear: + case CMD_smapclear: + case CMD_xmapclear: + xp->xp_context = EXPAND_MAPCLEAR; + xp->xp_pattern = (char_u *)arg; + break; + case CMD_abbreviate: case CMD_noreabbrev: case CMD_cabbrev: case CMD_cnoreabbrev: case CMD_iabbrev: case CMD_inoreabbrev: @@ -3441,6 +3454,13 @@ const char * set_one_cmd_context( xp->xp_pattern = (char_u *)arg; break; + case CMD_argdelete: + while ((xp->xp_pattern = vim_strchr((const char_u *)arg, ' ')) != NULL) { + arg = (const char *)(xp->xp_pattern + 1); + } + xp->xp_context = EXPAND_ARGLIST; + xp->xp_pattern = (char_u *)arg; + break; default: break; @@ -4846,6 +4866,7 @@ static struct { */ static const char *command_complete[] = { + [EXPAND_ARGLIST] = "arglist", [EXPAND_AUGROUP] = "augroup", [EXPAND_BEHAVE] = "behave", [EXPAND_BUFFERS] = "buffer", @@ -4870,6 +4891,7 @@ static const char *command_complete[] = #ifdef HAVE_WORKING_LIBINTL [EXPAND_LOCALES] = "locale", #endif + [EXPAND_MAPCLEAR] = "mapclear", [EXPAND_MAPPINGS] = "mapping", [EXPAND_MENUS] = "menu", [EXPAND_MESSAGES] = "messages", @@ -8370,23 +8392,25 @@ ssize_t find_cmdline_var(const char_u *src, size_t *usedlen) "%", #define SPEC_PERC 0 "#", -#define SPEC_HASH 1 - "<cword>", /* cursor word */ -#define SPEC_CWORD 2 - "<cWORD>", /* cursor WORD */ -#define SPEC_CCWORD 3 - "<cfile>", /* cursor path name */ -#define SPEC_CFILE 4 - "<sfile>", /* ":so" file name */ -#define SPEC_SFILE 5 - "<slnum>", /* ":so" file line number */ -#define SPEC_SLNUM 6 - "<afile>", /* autocommand file name */ -# define SPEC_AFILE 7 - "<abuf>", /* autocommand buffer number */ -# define SPEC_ABUF 8 - "<amatch>", /* autocommand match name */ -# define SPEC_AMATCH 9 +#define SPEC_HASH (SPEC_PERC + 1) + "<cword>", // cursor word +#define SPEC_CWORD (SPEC_HASH + 1) + "<cWORD>", // cursor WORD +#define SPEC_CCWORD (SPEC_CWORD + 1) + "<cexpr>", // expr under cursor +#define SPEC_CEXPR (SPEC_CCWORD + 1) + "<cfile>", // cursor path name +#define SPEC_CFILE (SPEC_CEXPR + 1) + "<sfile>", // ":so" file name +#define SPEC_SFILE (SPEC_CFILE + 1) + "<slnum>", // ":so" file line number +#define SPEC_SLNUM (SPEC_SFILE + 1) + "<afile>", // autocommand file name +#define SPEC_AFILE (SPEC_SLNUM + 1) + "<abuf>", // autocommand buffer number +#define SPEC_ABUF (SPEC_AFILE + 1) + "<amatch>", // autocommand match name +#define SPEC_AMATCH (SPEC_ABUF + 1) }; for (size_t i = 0; i < ARRAY_SIZE(spec_str); ++i) { @@ -8467,10 +8491,16 @@ eval_vars ( /* * word or WORD under cursor */ - if (spec_idx == SPEC_CWORD || spec_idx == SPEC_CCWORD) { - resultlen = find_ident_under_cursor(&result, (spec_idx == SPEC_CWORD - ? (FIND_IDENT|FIND_STRING) - : FIND_STRING)); + if (spec_idx == SPEC_CWORD + || spec_idx == SPEC_CCWORD + || spec_idx == SPEC_CEXPR) { + resultlen = find_ident_under_cursor( + &result, + spec_idx == SPEC_CWORD + ? (FIND_IDENT | FIND_STRING) + : (spec_idx == SPEC_CEXPR + ? (FIND_IDENT | FIND_STRING | FIND_EVAL) + : FIND_STRING)); if (resultlen == 0) { *errormsg = (char_u *)""; return NULL; @@ -8507,9 +8537,13 @@ eval_vars ( if (*s == '<') /* "#<99" uses v:oldfiles */ ++s; i = getdigits_int(&s); - *usedlen = (size_t)(s - src); /* length of what we expand */ + if (s == src + 2 && src[1] == '-') { + // just a minus sign, don't skip over it + s--; + } + *usedlen = (size_t)(s - src); // length of what we expand - if (src[1] == '<') { + if (src[1] == '<' && i != 0) { if (*usedlen < 2) { /* Should we give an error message for #<text? */ *usedlen = 1; @@ -8522,6 +8556,9 @@ eval_vars ( return NULL; } } else { + if (i == 0 && src[1] == '<' && *usedlen > 1) { + *usedlen = 1; + } buf = buflist_findnr(i); if (buf == NULL) { *errormsg = (char_u *)_( @@ -9655,6 +9692,14 @@ char_u *get_messages_arg(expand_T *xp FUNC_ATTR_UNUSED, int idx) return NULL; } +char_u *get_mapclear_arg(expand_T *xp FUNC_ATTR_UNUSED, int idx) +{ + if (idx == 0) { + return (char_u *)"<buffer>"; + } + return NULL; +} + static TriState filetype_detect = kNone; static TriState filetype_plugin = kNone; static TriState filetype_indent = kNone; diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 7f40a984d1..da1681520b 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -3290,17 +3290,18 @@ void restore_cmdline_alloc(char_u *p) /// @returns FAIL for failure, OK otherwise static bool cmdline_paste(int regname, bool literally, bool remcr) { - long i; char_u *arg; char_u *p; - int allocated; + bool allocated; struct cmdline_info save_ccline; /* check for valid regname; also accept special characters for CTRL-R in * the command line */ if (regname != Ctrl_F && regname != Ctrl_P && regname != Ctrl_W - && regname != Ctrl_A && !valid_yank_reg(regname, false)) + && regname != Ctrl_A && regname != Ctrl_L + && !valid_yank_reg(regname, false)) { return FAIL; + } /* A register containing CTRL-R can cause an endless loop. Allow using * CTRL-C to break the loop. */ @@ -3312,9 +3313,9 @@ static bool cmdline_paste(int regname, bool literally, bool remcr) /* Need to save and restore ccline. And set "textlock" to avoid nasty * things like going to another buffer when evaluating an expression. */ save_cmdline(&save_ccline); - ++textlock; - i = get_spec_reg(regname, &arg, &allocated, TRUE); - --textlock; + textlock++; + const bool i = get_spec_reg(regname, &arg, &allocated, true); + textlock--; restore_cmdline(&save_ccline); if (i) { @@ -4760,6 +4761,7 @@ ExpandFromContext ( } tab[] = { { EXPAND_COMMANDS, get_command_name, false, true }, { EXPAND_BEHAVE, get_behave_arg, true, true }, + { EXPAND_MAPCLEAR, get_mapclear_arg, true, true }, { EXPAND_MESSAGES, get_messages_arg, true, true }, { EXPAND_HISTORY, get_history_arg, true, true }, { EXPAND_USER_COMMANDS, get_user_commands, false, true }, @@ -4787,6 +4789,7 @@ ExpandFromContext ( #endif { EXPAND_ENV_VARS, get_env_name, true, true }, { EXPAND_USER, get_users, true, false }, + { EXPAND_ARGLIST, get_arglist_name, true, false }, }; int i; diff --git a/src/nvim/normal.c b/src/nvim/normal.c index 225fe4aa9a..afddd548a3 100644 --- a/src/nvim/normal.c +++ b/src/nvim/normal.c @@ -2990,6 +2990,43 @@ void reset_VIsual(void) } } +// Check for a balloon-eval special item to include when searching for an +// identifier. When "dir" is BACKWARD "ptr[-1]" must be valid! +// Returns true if the character at "*ptr" should be included. +// "dir" is FORWARD or BACKWARD, the direction of searching. +// "*colp" is in/decremented if "ptr[-dir]" should also be included. +// "bnp" points to a counter for square brackets. +static bool find_is_eval_item( + const char_u *const ptr, + int *const colp, + int *const bnp, + const int dir) +{ + // Accept everything inside []. + if ((*ptr == ']' && dir == BACKWARD) || (*ptr == '[' && dir == FORWARD)) { + *bnp += 1; + } + if (*bnp > 0) { + if ((*ptr == '[' && dir == BACKWARD) || (*ptr == ']' && dir == FORWARD)) { + *bnp -= 1; + } + return true; + } + + // skip over "s.var" + if (*ptr == '.') { + return true; + } + + // two-character item: s->var + if (ptr[dir == BACKWARD ? 0 : 1] == '>' + && ptr[dir == BACKWARD ? -1 : 0] == '-') { + *colp += dir; + return true; + } + return false; +} + /* * Find the identifier under or to the right of the cursor. * "find_type" can have one of three values: @@ -3030,6 +3067,7 @@ size_t find_ident_at_pos(win_T *wp, linenr_T lnum, colnr_T startcol, int this_class = 0; int prev_class; int prevcol; + int bn = 0; // bracket nesting /* * if i == 0: try to find an identifier @@ -3041,71 +3079,62 @@ size_t find_ident_at_pos(win_T *wp, linenr_T lnum, colnr_T startcol, * 1. skip to start of identifier/string */ col = startcol; - if (has_mbyte) { - while (ptr[col] != NUL) { - this_class = mb_get_class(ptr + col); - if (this_class != 0 && (i == 1 || this_class != 1)) - break; - col += (*mb_ptr2len)(ptr + col); + while (ptr[col] != NUL) { + // Stop at a ']' to evaluate "a[x]". + if ((find_type & FIND_EVAL) && ptr[col] == ']') { + break; } - } else - while (ptr[col] != NUL - && (i == 0 ? !vim_iswordc(ptr[col]) : ascii_iswhite(ptr[col])) - ) - ++col; + this_class = mb_get_class(ptr + col); + if (this_class != 0 && (i == 1 || this_class != 1)) { + break; + } + col += utfc_ptr2len(ptr + col); + } + // When starting on a ']' count it, so that we include the '['. + bn = ptr[col] == ']'; /* * 2. Back up to start of identifier/string. */ - if (has_mbyte) { - /* Remember class of character under cursor. */ + // Remember class of character under cursor. + if ((find_type & FIND_EVAL) && ptr[col] == ']') { + this_class = mb_get_class((char_u *)"a"); + } else { this_class = mb_get_class(ptr + col); - while (col > 0 && this_class != 0) { - prevcol = col - 1 - (*mb_head_off)(ptr, ptr + col - 1); - prev_class = mb_get_class(ptr + prevcol); - if (this_class != prev_class - && (i == 0 - || prev_class == 0 - || (find_type & FIND_IDENT)) - ) - break; - col = prevcol; - } - - /* If we don't want just any old string, or we've found an - * identifier, stop searching. */ - if (this_class > 2) - this_class = 2; - if (!(find_type & FIND_STRING) || this_class == 2) + } + while (col > 0 && this_class != 0) { + prevcol = col - 1 - utf_head_off(ptr, ptr + col - 1); + prev_class = mb_get_class(ptr + prevcol); + if (this_class != prev_class + && (i == 0 + || prev_class == 0 + || (find_type & FIND_IDENT)) + && (!(find_type & FIND_EVAL) + || prevcol == 0 + || !find_is_eval_item(ptr + prevcol, &prevcol, &bn, BACKWARD))) { break; - } else { - while (col > 0 - && ((i == 0 - ? vim_iswordc(ptr[col - 1]) - : (!ascii_iswhite(ptr[col - 1]) - && (!(find_type & FIND_IDENT) - || !vim_iswordc(ptr[col - 1])))) - )) - --col; + } + col = prevcol; + } - /* If we don't want just any old string, or we've found an - * identifier, stop searching. */ - if (!(find_type & FIND_STRING) || vim_iswordc(ptr[col])) - break; + // If we don't want just any old string, or we've found an + // identifier, stop searching. + if (this_class > 2) { + this_class = 2; + } + if (!(find_type & FIND_STRING) || this_class == 2) { + break; } } - if (ptr[col] == NUL || (i == 0 && ( - has_mbyte ? this_class != 2 : - !vim_iswordc(ptr[col])))) { - /* - * didn't find an identifier or string - */ - if (find_type & FIND_STRING) + if (ptr[col] == NUL || (i == 0 && this_class != 2)) { + // didn't find an identifier or string + if (find_type & FIND_STRING) { EMSG(_("E348: No string under cursor")); - else + } else { EMSG(_(e_noident)); + } return 0; } ptr += col; @@ -3114,21 +3143,20 @@ size_t find_ident_at_pos(win_T *wp, linenr_T lnum, colnr_T startcol, /* * 3. Find the end if the identifier/string. */ + bn = 0; + startcol -= col; col = 0; - if (has_mbyte) { - /* Search for point of changing multibyte character class. */ - this_class = mb_get_class(ptr); - while (ptr[col] != NUL - && ((i == 0 ? mb_get_class(ptr + col) == this_class - : mb_get_class(ptr + col) != 0) - )) - col += (*mb_ptr2len)(ptr + col); - } else - while ((i == 0 ? vim_iswordc(ptr[col]) - : (ptr[col] != NUL && !ascii_iswhite(ptr[col]))) - ) { - ++col; - } + // Search for point of changing multibyte character class. + this_class = mb_get_class(ptr); + while (ptr[col] != NUL + && ((i == 0 + ? mb_get_class(ptr + col) == this_class + : mb_get_class(ptr + col) != 0) + || ((find_type & FIND_EVAL) + && col <= (int)startcol + && find_is_eval_item(ptr + col, &col, &bn, FORWARD)))) { + col += utfc_ptr2len(ptr + col); + } assert(col >= 0); return (size_t)col; diff --git a/src/nvim/ops.c b/src/nvim/ops.c index 7defde731a..ff02d82ff3 100644 --- a/src/nvim/ops.c +++ b/src/nvim/ops.c @@ -1110,7 +1110,7 @@ int insert_reg( ) { int retval = OK; - int allocated; + bool allocated; /* * It is possible to get into an endless loop by having CTRL-R a in @@ -1187,82 +1187,92 @@ static void stuffescaped(const char *arg, int literally) } } -/* - * If "regname" is a special register, return TRUE and store a pointer to its - * value in "argp". - */ -int get_spec_reg( +// If "regname" is a special register, return true and store a pointer to its +// value in "argp". +bool get_spec_reg( int regname, char_u **argp, - int *allocated, /* return: TRUE when value was allocated */ - int errmsg /* give error message when failing */ + bool *allocated, // return: true when value was allocated + bool errmsg // give error message when failing ) { size_t cnt; *argp = NULL; - *allocated = FALSE; + *allocated = false; switch (regname) { case '%': /* file name */ if (errmsg) check_fname(); /* will give emsg if not set */ *argp = curbuf->b_fname; - return TRUE; + return true; - case '#': /* alternate file name */ - *argp = getaltfname(errmsg); /* may give emsg if not set */ - return TRUE; + case '#': // alternate file name + *argp = getaltfname(errmsg); // may give emsg if not set + return true; case '=': /* result of expression */ *argp = get_expr_line(); - *allocated = TRUE; - return TRUE; + *allocated = true; + return true; case ':': /* last command line */ if (last_cmdline == NULL && errmsg) EMSG(_(e_nolastcmd)); *argp = last_cmdline; - return TRUE; + return true; case '/': /* last search-pattern */ if (last_search_pat() == NULL && errmsg) EMSG(_(e_noprevre)); *argp = last_search_pat(); - return TRUE; + return true; case '.': /* last inserted text */ *argp = get_last_insert_save(); - *allocated = TRUE; - if (*argp == NULL && errmsg) + *allocated = true; + if (*argp == NULL && errmsg) { EMSG(_(e_noinstext)); - return TRUE; + } + return true; - case Ctrl_F: /* Filename under cursor */ - case Ctrl_P: /* Path under cursor, expand via "path" */ - if (!errmsg) - return FALSE; - *argp = file_name_at_cursor(FNAME_MESS | FNAME_HYP - | (regname == Ctrl_P ? FNAME_EXP : 0), 1L, NULL); - *allocated = TRUE; - return TRUE; + case Ctrl_F: // Filename under cursor + case Ctrl_P: // Path under cursor, expand via "path" + if (!errmsg) { + return false; + } + *argp = file_name_at_cursor( + FNAME_MESS | FNAME_HYP | (regname == Ctrl_P ? FNAME_EXP : 0), + 1L, NULL); + *allocated = true; + return true; - case Ctrl_W: /* word under cursor */ - case Ctrl_A: /* WORD (mnemonic All) under cursor */ - if (!errmsg) - return FALSE; + case Ctrl_W: // word under cursor + case Ctrl_A: // WORD (mnemonic All) under cursor + if (!errmsg) { + return false; + } cnt = find_ident_under_cursor(argp, (regname == Ctrl_W ? (FIND_IDENT|FIND_STRING) : FIND_STRING)); *argp = cnt ? vim_strnsave(*argp, cnt) : NULL; - *allocated = TRUE; - return TRUE; + *allocated = true; + return true; + + case Ctrl_L: // Line under cursor + if (!errmsg) { + return false; + } + + *argp = ml_get_buf(curwin->w_buffer, curwin->w_cursor.lnum, false); + return true; case '_': /* black hole: always empty */ *argp = (char_u *)""; - return TRUE; + return true; } - return FALSE; + return false; } /// Paste a yank register into the command line. @@ -2652,7 +2662,7 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags) int lendiff = 0; pos_T old_pos; char_u *insert_string = NULL; - int allocated = FALSE; + bool allocated = false; long cnt; if (flags & PUT_FIXINDENT) @@ -2748,9 +2758,10 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags) * For special registers '%' (file name), '#' (alternate file name) and * ':' (last command line), etc. we have to create a fake yank register. */ - if (get_spec_reg(regname, &insert_string, &allocated, TRUE)) { - if (insert_string == NULL) + if (get_spec_reg(regname, &insert_string, &allocated, true)) { + if (insert_string == NULL) { return; + } } if (!curbuf->terminal) { @@ -4907,10 +4918,11 @@ void *get_reg_contents(int regname, int flags) return NULL; char_u *retval; - int allocated; - if (get_spec_reg(regname, &retval, &allocated, FALSE)) { - if (retval == NULL) + bool allocated; + if (get_spec_reg(regname, &retval, &allocated, false)) { + if (retval == NULL) { return NULL; + } if (allocated) { return get_reg_wrap_one_line(retval, flags); } diff --git a/src/nvim/testdir/test_cmdline.vim b/src/nvim/testdir/test_cmdline.vim index 5a43838218..c302948ba3 100644 --- a/src/nvim/testdir/test_cmdline.vim +++ b/src/nvim/testdir/test_cmdline.vim @@ -137,6 +137,11 @@ func Test_getcompletion() let l = getcompletion('v:notexists', 'var') call assert_equal([], l) + args a.c b.c + let l = getcompletion('', 'arglist') + call assert_equal(['a.c', 'b.c'], l) + %argdelete + let l = getcompletion('', 'augroup') call assert_true(index(l, 'END') >= 0) let l = getcompletion('blahblah', 'augroup') @@ -222,6 +227,11 @@ func Test_getcompletion() let l = getcompletion('not', 'messages') call assert_equal([], l) + let l = getcompletion('', 'mapclear') + call assert_true(index(l, '<buffer>') >= 0) + let l = getcompletion('not', 'mapclear') + call assert_equal([], l) + if has('cscope') let l = getcompletion('', 'cscope') let cmds = ['add', 'find', 'help', 'kill', 'reset', 'show'] @@ -311,6 +321,9 @@ func Test_paste_in_cmdline() call feedkeys("ft:aaa \<C-R>\<C-F> bbb\<C-B>\"\<CR>", 'tx') call assert_equal('"aaa /tmp/some bbb', @:) + call feedkeys(":aaa \<C-R>\<C-L> bbb\<C-B>\"\<CR>", 'tx') + call assert_equal('"aaa '.getline(1).' bbb', @:) + set incsearch call feedkeys("fy:aaa veryl\<C-R>\<C-W> bbb\<C-B>\"\<CR>", 'tx') call assert_equal('"aaa verylongword bbb', @:) @@ -375,6 +388,27 @@ func Test_cmdline_complete_user_cmd() delcommand Foo endfunc +func Test_cmdline_write_alternatefile() + new + call setline('.', ['one', 'two']) + f foo.txt + new + f #-A + call assert_equal('foo.txt-A', expand('%')) + f #<-B.txt + call assert_equal('foo-B.txt', expand('%')) + f %< + call assert_equal('foo-B', expand('%')) + new + call assert_fails('f #<', 'E95') + bw! + f foo-B.txt + f %<-A + call assert_equal('foo-B-A', expand('%')) + bw! + bw! +endfunc + " using a leading backslash here set cpo+=C @@ -430,6 +464,22 @@ func Test_getcmdtype() cunmap <F6> endfunc +func Test_getcmdwintype() + call feedkeys("q/:let a = getcmdwintype()\<CR>:q\<CR>", 'x!') + call assert_equal('/', a) + + call feedkeys("q?:let a = getcmdwintype()\<CR>:q\<CR>", 'x!') + call assert_equal('?', a) + + call feedkeys("q::let a = getcmdwintype()\<CR>:q\<CR>", 'x!') + call assert_equal(':', a) + + call feedkeys(":\<C-F>:let a = getcmdwintype()\<CR>:q\<CR>", 'x!') + call assert_equal(':', a) + + call assert_equal('', getcmdwintype()) +endfunc + func Test_verbosefile() set verbosefile=Xlog echomsg 'foo' @@ -440,4 +490,25 @@ func Test_verbosefile() call delete('Xlog') endfunc +func Test_setcmdpos() + func InsertTextAtPos(text, pos) + call assert_equal(0, setcmdpos(a:pos)) + return a:text + endfunc + + " setcmdpos() with position in the middle of the command line. + call feedkeys(":\"12\<C-R>=InsertTextAtPos('a', 3)\<CR>b\<CR>", 'xt') + call assert_equal('"1ab2', @:) + + call feedkeys(":\"12\<C-R>\<C-R>=InsertTextAtPos('a', 3)\<CR>b\<CR>", 'xt') + call assert_equal('"1b2a', @:) + + " setcmdpos() with position beyond the end of the command line. + call feedkeys(":\"12\<C-B>\<C-R>=InsertTextAtPos('a', 10)\<CR>b\<CR>", 'xt') + call assert_equal('"12ab', @:) + + " setcmdpos() returns 1 when not editing the command line. + call assert_equal(1, setcmdpos(3)) +endfunc + set cpo& diff --git a/src/nvim/testdir/test_normal.vim b/src/nvim/testdir/test_normal.vim index 4c63bd1f71..caa530e4aa 100644 --- a/src/nvim/testdir/test_normal.vim +++ b/src/nvim/testdir/test_normal.vim @@ -392,10 +392,31 @@ func! Test_normal10_expand() call setline(1, ['1', 'ifooar,,cbar']) 2 norm! $ - let a=expand('<cword>') - let b=expand('<cWORD>') - call assert_equal('cbar', a) - call assert_equal('ifooar,,cbar', b) + call assert_equal('cbar', expand('<cword>')) + call assert_equal('ifooar,,cbar', expand('<cWORD>')) + + call setline(1, ['prx = list[idx];']) + 1 + let expected = ['', 'prx', 'prx', 'prx', + \ 'list', 'list', 'list', 'list', 'list', 'list', 'list', + \ 'idx', 'idx', 'idx', 'idx', + \ 'list[idx]', + \ '];', + \ ] + for i in range(1, 16) + exe 'norm ' . i . '|' + call assert_equal(expected[i], expand('<cexpr>'), 'i == ' . i) + endfor + + if executable('echo') + " Test expand(`...`) i.e. backticks command expansion. + " MS-Windows has a trailing space. + call assert_match('^abcde *$', expand('`echo abcde`')) + endif + + " Test expand(`=...`) i.e. backticks expression expansion + call assert_equal('5', expand('`=2+3`')) + " clean up bw! endfunc @@ -1536,12 +1557,12 @@ fun! Test_normal29_brace() \ 'the ''{'' flag is in ''cpoptions'' then ''{'' in the first column is used as a', \ 'paragraph boundary |posix|.', \ '{', - \ 'This is no paragaraph', + \ 'This is no paragraph', \ 'unless the ''{'' is set', \ 'in ''cpoptions''', \ '}', \ '.IP', - \ 'The nroff macros IP seperates a paragraph', + \ 'The nroff macros IP separates a paragraph', \ 'That means, it must be a ''.''', \ 'followed by IP', \ '.LPIt does not matter, if afterwards some', @@ -1556,7 +1577,7 @@ fun! Test_normal29_brace() 1 norm! 0d2} call assert_equal(['.IP', - \ 'The nroff macros IP seperates a paragraph', 'That means, it must be a ''.''', 'followed by IP', + \ 'The nroff macros IP separates a paragraph', 'That means, it must be a ''.''', 'followed by IP', \ '.LPIt does not matter, if afterwards some', 'more characters follow.', '.SHAlso section boundaries from the nroff', \ 'macros terminate a paragraph. That means', 'a character like this:', '.NH', 'End of text here', ''], getline(1,'$')) norm! 0d} @@ -1576,21 +1597,21 @@ fun! Test_normal29_brace() " set cpo+={ " 1 " norm! 0d2} - " call assert_equal(['{', 'This is no paragaraph', 'unless the ''{'' is set', 'in ''cpoptions''', '}', - " \ '.IP', 'The nroff macros IP seperates a paragraph', 'That means, it must be a ''.''', + " call assert_equal(['{', 'This is no paragraph', 'unless the ''{'' is set', 'in ''cpoptions''', '}', + " \ '.IP', 'The nroff macros IP separates a paragraph', 'That means, it must be a ''.''', " \ 'followed by IP', '.LPIt does not matter, if afterwards some', 'more characters follow.', " \ '.SHAlso section boundaries from the nroff', 'macros terminate a paragraph. That means', " \ 'a character like this:', '.NH', 'End of text here', ''], getline(1,'$')) " $ " norm! d} - " call assert_equal(['{', 'This is no paragaraph', 'unless the ''{'' is set', 'in ''cpoptions''', '}', - " \ '.IP', 'The nroff macros IP seperates a paragraph', 'That means, it must be a ''.''', + " call assert_equal(['{', 'This is no paragraph', 'unless the ''{'' is set', 'in ''cpoptions''', '}', + " \ '.IP', 'The nroff macros IP separates a paragraph', 'That means, it must be a ''.''', " \ 'followed by IP', '.LPIt does not matter, if afterwards some', 'more characters follow.', " \ '.SHAlso section boundaries from the nroff', 'macros terminate a paragraph. That means', " \ 'a character like this:', '.NH', 'End of text here', ''], getline(1,'$')) " norm! gg} " norm! d5} - " call assert_equal(['{', 'This is no paragaraph', 'unless the ''{'' is set', 'in ''cpoptions''', '}', ''], getline(1,'$')) + " call assert_equal(['{', 'This is no paragraph', 'unless the ''{'' is set', 'in ''cpoptions''', '}', ''], getline(1,'$')) " clean up set cpo-={ diff --git a/src/nvim/vim.h b/src/nvim/vim.h index bddf092789..767936ecee 100644 --- a/src/nvim/vim.h +++ b/src/nvim/vim.h @@ -155,6 +155,8 @@ enum { EXPAND_USER_ADDR_TYPE, EXPAND_PACKADD, EXPAND_MESSAGES, + EXPAND_MAPCLEAR, + EXPAND_ARGLIST, EXPAND_CHECKHEALTH, }; |