aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/nvim/ex_cmds.lua8
-rw-r--r--src/nvim/ex_cmds_defs.h2
-rw-r--r--src/nvim/ex_docmd.c197
-rw-r--r--src/nvim/ex_getln.c1
-rw-r--r--src/nvim/testdir/Makefile3
-rw-r--r--src/nvim/testdir/test_command_count.in50
-rw-r--r--src/nvim/testdir/test_command_count.ok17
-rw-r--r--src/nvim/version.c2
-rw-r--r--src/nvim/vim.h1
9 files changed, 241 insertions, 40 deletions
diff --git a/src/nvim/ex_cmds.lua b/src/nvim/ex_cmds.lua
index 3ead26120e..2c61d330c7 100644
--- a/src/nvim/ex_cmds.lua
+++ b/src/nvim/ex_cmds.lua
@@ -32,7 +32,7 @@ local ADDR_LINES = 0
local ADDR_WINDOWS = 1
local ADDR_ARGUMENTS = 2
local ADDR_LOADED_BUFFERS = 3
-local ADDR_UNLOADED_BUFFERS = 4
+local ADDR_BUFFERS = 4
local ADDR_TABS = 5
-- The following table is described in ex_cmds_defs.h file.
@@ -154,7 +154,7 @@ return {
{
command='buffer',
flags=bit.bor(BANG, RANGE, NOTADR, BUFNAME, BUFUNL, COUNT, EXTRA, EDITCMD, TRLBAR),
- addr_type=ADDR_UNLOADED_BUFFERS,
+ addr_type=ADDR_BUFFERS,
func='ex_buffer',
},
{
@@ -286,7 +286,7 @@ return {
{
command='bwipeout',
flags=bit.bor(BANG, RANGE, NOTADR, BUFNAME, BUFUNL, COUNT, EXTRA, TRLBAR),
- addr_type=ADDR_UNLOADED_BUFFERS,
+ addr_type=ADDR_BUFFERS,
func='ex_bunload',
},
{
@@ -2194,7 +2194,7 @@ return {
{
command='sbuffer',
flags=bit.bor(BANG, RANGE, NOTADR, BUFNAME, BUFUNL, COUNT, EXTRA, EDITCMD, TRLBAR),
- addr_type=ADDR_UNLOADED_BUFFERS,
+ addr_type=ADDR_BUFFERS,
func='ex_buffer',
},
{
diff --git a/src/nvim/ex_cmds_defs.h b/src/nvim/ex_cmds_defs.h
index 4703e9b8ad..4065cc2fdc 100644
--- a/src/nvim/ex_cmds_defs.h
+++ b/src/nvim/ex_cmds_defs.h
@@ -76,7 +76,7 @@
#define ADDR_WINDOWS 1
#define ADDR_ARGUMENTS 2
#define ADDR_LOADED_BUFFERS 3
-#define ADDR_UNLOADED_BUFFERS 4
+#define ADDR_BUFFERS 4
#define ADDR_TABS 5
typedef struct exarg exarg_T;
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index 521aa99b58..75d324b421 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -85,6 +85,7 @@ typedef struct ucmd {
char_u *uc_rep; /* The command's replacement string */
long uc_def; /* The default value for a range/count */
int uc_compl; /* completion type */
+ int uc_addr_type; /* The command's address type */
scid_T uc_scriptID; /* SID where the command was defined */
char_u *uc_compl_arg; /* completion argument if any */
} ucmd_T;
@@ -1422,7 +1423,10 @@ static char_u * do_one_cmd(char_u **cmdlinep,
if (ea.cmdidx != CMD_USER && ea.cmdidx != CMD_SIZE) {
ea.addr_type = cmdnames[(int)ea.cmdidx].cmd_addr_type;
} else {
- ea.addr_type = ADDR_LINES;
+ if (ea.cmdidx != CMD_USER) {
+ ea.addr_type = ADDR_LINES;
+ // ea.addr_type for user commands is set by find_ucmd
+ }
}
ea.cmd = cmd;
@@ -1442,7 +1446,7 @@ static char_u * do_one_cmd(char_u **cmdlinep,
ea.line2 = curwin->w_arg_idx + 1;
break;
case ADDR_LOADED_BUFFERS:
- case ADDR_UNLOADED_BUFFERS:
+ case ADDR_BUFFERS:
ea.line2 = curbuf->b_fnum;
break;
case ADDR_TABS:
@@ -1470,18 +1474,30 @@ static char_u * do_one_cmd(char_u **cmdlinep,
}
ea.line2 = buf->b_fnum;
break;
- case ADDR_UNLOADED_BUFFERS:
+ case ADDR_BUFFERS:
ea.line1 = firstbuf->b_fnum;
ea.line2 = lastbuf->b_fnum;
break;
case ADDR_WINDOWS:
case ADDR_TABS:
- errormsg = (char_u *)_(e_invrange);
- goto doend;
+ if (IS_USER_CMDIDX(ea.cmdidx)) {
+ ea.line1 = 1;
+ ea.line2 =
+ ea.addr_type == ADDR_WINDOWS ? LAST_WIN_NR : LAST_TAB_NR;
+ } else {
+ // there is no Vim command which uses '%' and
+ // ADDR_WINDOWS or ADDR_TABS
+ errormsg = (char_u *)_(e_invrange);
+ goto doend;
+ }
break;
case ADDR_ARGUMENTS:
- ea.line1 = 1;
- ea.line2 = ARGCOUNT;
+ if (ARGCOUNT == 0) {
+ ea.line1 = ea.line2 = 0;
+ } else {
+ ea.line1 = 1;
+ ea.line2 = ARGCOUNT;
+ }
break;
}
++ea.addr_count;
@@ -1832,8 +1848,43 @@ static char_u * do_one_cmd(char_u **cmdlinep,
}
if ((ea.argt & DFLALL) && ea.addr_count == 0) {
+ buf_T *buf;
+
ea.line1 = 1;
- ea.line2 = curbuf->b_ml.ml_line_count;
+ switch (ea.addr_type) {
+ case ADDR_LINES:
+ ea.line2 = curbuf->b_ml.ml_line_count;
+ break;
+ case ADDR_LOADED_BUFFERS:
+ buf = firstbuf;
+ while (buf->b_next != NULL && buf->b_ml.ml_mfp == NULL) {
+ buf = buf->b_next;
+ }
+ ea.line1 = buf->b_fnum;
+ buf = lastbuf;
+ while (buf->b_prev != NULL && buf->b_ml.ml_mfp == NULL) {
+ buf = buf->b_prev;
+ }
+ ea.line2 = buf->b_fnum;
+ break;
+ case ADDR_BUFFERS:
+ ea.line1 = firstbuf->b_fnum;
+ ea.line2 = lastbuf->b_fnum;
+ break;
+ case ADDR_WINDOWS:
+ ea.line2 = LAST_WIN_NR;
+ break;
+ case ADDR_TABS:
+ ea.line2 = LAST_TAB_NR;
+ break;
+ case ADDR_ARGUMENTS:
+ if (ARGCOUNT == 0) {
+ ea.line1 = ea.line2 = 0;
+ } else {
+ ea.line2 = ARGCOUNT;
+ }
+ break;
+ }
}
/* accept numbered register only when no count allowed (:put) */
@@ -2332,6 +2383,7 @@ find_ucmd (
eap->cmdidx = CMD_USER_BUF;
eap->argt = uc->uc_argt;
eap->useridx = j;
+ eap->addr_type = uc->uc_addr_type;
if (compl != NULL)
*compl = uc->uc_compl;
@@ -2871,9 +2923,8 @@ set_one_cmd_context (
return NULL;
}
- /* For the -complete and -nargs attributes, we complete
- * their arguments as well.
- */
+ // For the -complete, -nargs and -addr attributes, we complete
+ // their arguments as well.
if (STRNICMP(arg, "complete", p - arg) == 0) {
xp->xp_context = EXPAND_USER_COMPLETE;
xp->xp_pattern = p + 1;
@@ -2882,6 +2933,10 @@ set_one_cmd_context (
xp->xp_context = EXPAND_USER_NARGS;
xp->xp_pattern = p + 1;
return NULL;
+ } else if (STRNICMP(arg, "addr", p - arg) == 0) {
+ xp->xp_context = EXPAND_USER_ADDR_TYPE;
+ xp->xp_pattern = p + 1;
+ return NULL;
}
return NULL;
}
@@ -3267,7 +3322,7 @@ static linenr_T get_address(char_u **ptr,
lnum = curwin->w_arg_idx + 1;
break;
case ADDR_LOADED_BUFFERS:
- case ADDR_UNLOADED_BUFFERS:
+ case ADDR_BUFFERS:
lnum = curbuf->b_fnum;
break;
case ADDR_TABS:
@@ -3298,7 +3353,7 @@ static linenr_T get_address(char_u **ptr,
}
lnum = buf->b_fnum;
break;
- case ADDR_UNLOADED_BUFFERS:
+ case ADDR_BUFFERS:
lnum = lastbuf->b_fnum;
break;
case ADDR_TABS:
@@ -3437,7 +3492,7 @@ static linenr_T get_address(char_u **ptr,
lnum = curwin->w_arg_idx + 1;
break;
case ADDR_LOADED_BUFFERS:
- case ADDR_UNLOADED_BUFFERS:
+ case ADDR_BUFFERS:
lnum = curbuf->b_fnum;
break;
case ADDR_TABS:
@@ -3454,10 +3509,8 @@ static linenr_T get_address(char_u **ptr,
n = 1;
else
n = getdigits(&cmd);
- if (addr_type == ADDR_LOADED_BUFFERS ||
- addr_type == ADDR_UNLOADED_BUFFERS)
- lnum = compute_buffer_local_count(addr_type, lnum,
- (i == '-') ? -1 * n : n);
+ if (addr_type == ADDR_LOADED_BUFFERS || addr_type == ADDR_BUFFERS)
+ lnum = compute_buffer_local_count(addr_type, lnum, (i == '-') ? -1 * n : n);
else if (i == '-')
lnum -= n;
else
@@ -3489,13 +3542,11 @@ static linenr_T get_address(char_u **ptr,
lnum = LAST_WIN_NR;
break;
case ADDR_LOADED_BUFFERS:
- case ADDR_UNLOADED_BUFFERS:
+ case ADDR_BUFFERS:
if (lnum < firstbuf->b_fnum) {
lnum = firstbuf->b_fnum;
break;
}
- if (lnum > lastbuf->b_fnum)
- lnum = lastbuf->b_fnum;
break;
}
}
@@ -4342,10 +4393,9 @@ char_u *get_command_name(expand_T *xp, int idx)
return cmdnames[idx].cmd_name;
}
-
static int uc_add_command(char_u *name, size_t name_len, char_u *rep,
uint32_t argt, long def, int flags, int compl,
- char_u *compl_arg, int force)
+ char_u *compl_arg, int addr_type, int force)
{
ucmd_T *cmd = NULL;
char_u *p;
@@ -4420,6 +4470,7 @@ static int uc_add_command(char_u *name, size_t name_len, char_u *rep,
cmd->uc_compl = compl;
cmd->uc_scriptID = current_SID;
cmd->uc_compl_arg = compl_arg;
+ cmd->uc_addr_type = addr_type;
return OK;
@@ -4429,6 +4480,21 @@ fail:
return FAIL;
}
+
+static struct {
+ int expand;
+ char *name;
+} addr_type_complete[] =
+{
+ {ADDR_ARGUMENTS, "arguments"},
+ {ADDR_LINES, "lines"},
+ {ADDR_LOADED_BUFFERS, "loaded_buffers"},
+ {ADDR_TABS, "tabs"},
+ {ADDR_BUFFERS, "buffers"},
+ {ADDR_WINDOWS, "windows"},
+ {-1, NULL}
+};
+
/*
* List of names for completion for ":command" with the EXPAND_ flag.
* Must be alphabetical for completion.
@@ -4477,6 +4543,7 @@ static struct {
static void uc_list(char_u *name, size_t name_len)
{
+ int i, j;
int found = FALSE;
ucmd_T *cmd;
int len;
@@ -4485,7 +4552,6 @@ static void uc_list(char_u *name, size_t name_len)
gap = &curbuf->b_ucmds;
for (;; ) {
- int i;
for (i = 0; i < gap->ga_len; ++i) {
cmd = USER_CMD_GA(gap, i);
a = cmd->uc_argt;
@@ -4496,7 +4562,7 @@ static void uc_list(char_u *name, size_t name_len)
/* Put out the title first time */
if (!found)
- MSG_PUTS_TITLE(_("\n Name Args Range Complete Definition"));
+ MSG_PUTS_TITLE(_("\n Name Args Address Complete Definition"));
found = TRUE;
msg_putchar('\n');
if (got_int)
@@ -4551,8 +4617,21 @@ static void uc_list(char_u *name, size_t name_len)
IObuff[len++] = ' ';
} while (len < 11);
+ /* Address Type */
+ for (j = 0; addr_type_complete[j].expand != -1; ++j)
+ if (addr_type_complete[j].expand != ADDR_LINES &&
+ addr_type_complete[j].expand == cmd->uc_addr_type) {
+ STRCPY(IObuff + len, addr_type_complete[j].name);
+ len += (int)STRLEN(IObuff + len);
+ break;
+ }
+
+ do {
+ IObuff[len++] = ' ';
+ } while (len < 21);
+
/* Completion */
- for (int j = 0; command_complete[j].expand != 0; ++j)
+ for (j = 0; command_complete[j].expand != 0; ++j)
if (command_complete[j].expand == cmd->uc_compl) {
STRCPY(IObuff + len, command_complete[j].name);
len += (int)STRLEN(IObuff + len);
@@ -4561,7 +4640,7 @@ static void uc_list(char_u *name, size_t name_len)
do {
IObuff[len++] = ' ';
- } while (len < 21);
+ } while (len < 35);
IObuff[len] = '\0';
msg_outtrans(IObuff);
@@ -4597,7 +4676,9 @@ static char_u *uc_fun_cmd(void)
return IObuff;
}
-static int uc_scan_attr(char_u *attr, size_t len, uint32_t *argt, long *def, int *flags, int *compl, char_u **compl_arg)
+static int uc_scan_attr(char_u *attr, size_t len, uint32_t *argt, long *def,
+ int *flags, int * compl, char_u **compl_arg,
+ int *addr_type_arg)
{
char_u *p;
@@ -4696,6 +4777,18 @@ invalid_count:
if (parse_compl_arg(val, (int)vallen, compl, argt, compl_arg)
== FAIL)
return FAIL;
+ } else if (STRNICMP(attr, "addr", attrlen) == 0) {
+ *argt |= RANGE;
+ if (val == NULL) {
+ EMSG(_("E179: argument required for -addr"));
+ return FAIL;
+ }
+ if (parse_addr_type_arg(val, (int)vallen, argt, addr_type_arg) == FAIL) {
+ return FAIL;
+ }
+ if (addr_type_arg != ADDR_LINES) {
+ *argt |= (ZEROR | NOTADR);
+ }
} else {
char_u ch = attr[len];
attr[len] = '\0';
@@ -4721,6 +4814,7 @@ static void ex_command(exarg_T *eap)
int flags = 0;
int compl = EXPAND_NOTHING;
char_u *compl_arg = NULL;
+ int addr_type_arg = ADDR_LINES;
int has_attr = (eap->arg[0] == '-');
int name_len;
@@ -4730,7 +4824,7 @@ static void ex_command(exarg_T *eap)
while (*p == '-') {
++p;
end = skiptowhite(p);
- if (uc_scan_attr(p, end - p, &argt, &def, &flags, &compl, &compl_arg)
+ if (uc_scan_attr(p, end - p, &argt, &def, &flags, &compl, &compl_arg, &addr_type_arg)
== FAIL)
return;
p = skipwhite(end);
@@ -4764,7 +4858,7 @@ static void ex_command(exarg_T *eap)
return;
} else
uc_add_command(name, end - name, p, argt, def, flags, compl, compl_arg,
- eap->forceit);
+ addr_type_arg, eap->forceit);
}
/*
@@ -5192,6 +5286,13 @@ static char_u *get_user_command_name(int idx)
{
return get_user_commands(NULL, idx - (int)CMD_SIZE);
}
+/*
+ * Function given to ExpandGeneric() to obtain the list of user address type names.
+ */
+char_u *get_user_cmd_addr_type(expand_T *xp, int idx)
+{
+ return (char_u *)addr_type_complete[idx].name;
+}
/*
* Function given to ExpandGeneric() to obtain the list of user command names.
@@ -5212,9 +5313,9 @@ char_u *get_user_commands(expand_T *xp, int idx)
*/
char_u *get_user_cmd_flags(expand_T *xp, int idx)
{
- static char *user_cmd_flags[] =
- {"bang", "bar", "buffer", "complete", "count",
- "nargs", "range", "register"};
+ static char *user_cmd_flags[] = {"addr", "bang", "bar",
+ "buffer", "complete", "count",
+ "nargs", "range", "register"};
if (idx >= (int)ARRAY_SIZE(user_cmd_flags))
return NULL;
@@ -5241,6 +5342,36 @@ char_u *get_user_cmd_complete(expand_T *xp, int idx)
return (char_u *)command_complete[idx].name;
}
+/*
+ * Parse address type argument
+ */
+int parse_addr_type_arg(char_u *value, int vallen, uint32_t *argt,
+ int *addr_type_arg)
+{
+ int i, a, b;
+ for (i = 0; addr_type_complete[i].expand != -1; ++i) {
+ a = (int)STRLEN(addr_type_complete[i].name) == vallen;
+ b = STRNCMP(value, addr_type_complete[i].name, vallen) == 0;
+ if (a && b) {
+ *addr_type_arg = addr_type_complete[i].expand;
+ break;
+ }
+ }
+
+ if (addr_type_complete[i].expand == -1) {
+ char_u *err = value;
+ for (i = 0; err[i] == NUL || !ascii_iswhite(err[i]); i++)
+ ;
+ err[i] = NUL;
+ EMSG2(_("E180: Invalid address type value: %s"), err);
+ return FAIL;
+ }
+
+ if (*addr_type_arg != ADDR_LINES)
+ *argt |= NOTADR;
+
+ return OK;
+}
/*
* Parse a completion argument "value[vallen]".
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c
index b54ae5fe11..1a04f1bd91 100644
--- a/src/nvim/ex_getln.c
+++ b/src/nvim/ex_getln.c
@@ -3701,6 +3701,7 @@ ExpandFromContext (
{EXPAND_BEHAVE, get_behave_arg, TRUE, TRUE},
{EXPAND_HISTORY, get_history_arg, TRUE, TRUE},
{EXPAND_USER_COMMANDS, get_user_commands, FALSE, TRUE},
+ {EXPAND_USER_ADDR_TYPE, get_user_cmd_addr_type, FALSE, TRUE},
{EXPAND_USER_CMD_FLAGS, get_user_cmd_flags, FALSE, TRUE},
{EXPAND_USER_NARGS, get_user_cmd_nargs, FALSE, TRUE},
{EXPAND_USER_COMPLETE, get_user_cmd_complete, FALSE, TRUE},
diff --git a/src/nvim/testdir/Makefile b/src/nvim/testdir/Makefile
index fb529e0cb2..fa68ab8d3a 100644
--- a/src/nvim/testdir/Makefile
+++ b/src/nvim/testdir/Makefile
@@ -31,7 +31,8 @@ SCRIPTS := test_autoformat_join.out \
test_listlbr.out \
test_breakindent.out \
test_argument_count.out \
- test_close_count.out
+ test_close_count.out \
+ test_command_count.out
SCRIPTS_GUI := test16.out
diff --git a/src/nvim/testdir/test_command_count.in b/src/nvim/testdir/test_command_count.in
new file mode 100644
index 0000000000..3697add746
--- /dev/null
+++ b/src/nvim/testdir/test_command_count.in
@@ -0,0 +1,50 @@
+Test for user command counts vim: set ft=vim :
+
+STARTTEST
+:let g:lines = []
+:so tiny.vim
+:com -range RangeLines :call add(g:lines, 'RangeLines '.<line1>.' '.<line2>)
+:com -range -addr=arguments RangeArguments :call add(g:lines, 'RangeArguments '.<line1>.' '.<line2>)
+:com -range=% -addr=arguments RangeArgumentsAll :call add(g:lines, 'RangeArgumentsAll '.<line1>.' '.<line2>)
+:com -range -addr=loaded_buffers RangeLoadedBuffers :call add(g:lines, 'RangeLoadedBuffers '.<line1>.' '.<line2>)
+:com -range=% -addr=loaded_buffers RangeLoadedBuffersAll :call add(g:lines, 'RangeLoadedBuffersAll '.<line1>.' '.<line2>)
+:com -range -addr=buffers RangeBuffers :call add(g:lines, 'RangeBuffers '.<line1>.' '.<line2>)
+:com -range=% -addr=buffers RangeBuffersAll :call add(g:lines, 'RangeBuffersAll '.<line1>.' '.<line2>)
+:com -range -addr=windows RangeWindows :call add(g:lines, 'RangeWindows '.<line1>.' '.<line2>)
+:com -range=% -addr=windows RangeWindowsAll :call add(g:lines, 'RangeWindowsAll '.<line1>.' '.<line2>)
+:com -range -addr=tabs RangeTabs :call add(g:lines, 'RangeTabs '.<line1>.' '.<line2>)
+:com -range=% -addr=tabs RangeTabsAll :call add(g:lines, 'RangeTabsAll '.<line1>.' '.<line2>)
+:set hidden
+:arga a b c d
+:argdo echo "loading buffers"
+:argu 3
+:.-,$-RangeArguments
+:%RangeArguments
+:RangeArgumentsAll
+:N
+:.RangeArguments
+:split|split|split|split
+:3wincmd w
+:.,$RangeWindows
+:%RangeWindows
+:RangeWindowsAll
+:only
+:blast|bd
+:.,$RangeLoadedBuffers
+:%RangeLoadedBuffers
+:RangeLoadedBuffersAll
+:.,$RangeBuffers
+:%RangeBuffers
+:RangeBuffersAll
+:tabe|tabe|tabe|tabe
+:normal 2gt
+:.,$RangeTabs
+:%RangeTabs
+:RangeTabsAll
+:1tabonly
+:e! test.out
+:call append(0, g:lines)
+:w|qa!
+ENDTEST
+
+
diff --git a/src/nvim/testdir/test_command_count.ok b/src/nvim/testdir/test_command_count.ok
new file mode 100644
index 0000000000..11e88b3903
--- /dev/null
+++ b/src/nvim/testdir/test_command_count.ok
@@ -0,0 +1,17 @@
+RangeArguments 2 4
+RangeArguments 1 5
+RangeArgumentsAll 1 5
+RangeArguments 2 2
+RangeWindows 3 5
+RangeWindows 1 5
+RangeWindowsAll 1 5
+RangeLoadedBuffers 2 4
+RangeLoadedBuffers 1 4
+RangeLoadedBuffersAll 1 4
+RangeBuffers 2 5
+RangeBuffers 1 5
+RangeBuffersAll 1 5
+RangeTabs 2 5
+RangeTabs 1 5
+RangeTabsAll 1 5
+
diff --git a/src/nvim/version.c b/src/nvim/version.c
index 505894feb2..6ff3652e4e 100644
--- a/src/nvim/version.c
+++ b/src/nvim/version.c
@@ -237,7 +237,7 @@ static int included_patches[] = {
545,
//544 NA
543,
- //542,
+ 542,
541,
//540 NA
539,
diff --git a/src/nvim/vim.h b/src/nvim/vim.h
index 41fcff129c..127e385619 100644
--- a/src/nvim/vim.h
+++ b/src/nvim/vim.h
@@ -182,6 +182,7 @@ enum {
EXPAND_HISTORY,
EXPAND_USER,
EXPAND_SYNTIME,
+ EXPAND_USER_ADDR_TYPE,
};