mirror of
https://github.com/neovim/neovim.git
synced 2024-12-19 18:55:14 -07:00
vim-patch:7.4.530-531
Specify different kinds of counts for commands. Updated ex commands generator scripts. Includes fixes to comments from patch 7.4.531 Original message: Problem: Many commands take a count or range that is not using line numbers. Solution: For each command specify what kind of count it uses. For windows, buffers and arguments have "$" and "." have a relevant meaning. (Marcin Szamotulski) https://code.google.com/p/vim/source/detail?r=v7-4-530 https://code.google.com/p/vim/source/detail?r=v7-4-531 Add legacy tests for 7.4.530 https://code.google.com/p/vim/source/detail?r=1e6d87a36dcdca231721dde8cbbc26610fb3df27
This commit is contained in:
parent
6a8862ded4
commit
86330fdd3f
@ -61,16 +61,25 @@ In the GUI tab pages line you can use the right mouse button to open menu.
|
||||
:[count]tabe[dit] *:tabe* *:tabedit* *:tabnew*
|
||||
:[count]tabnew
|
||||
Open a new tab page with an empty window, after the current
|
||||
tab page. For [count] see |:tab| below.
|
||||
tab page. If [count] is given the new tab page appears after
|
||||
the tabpage [count] otherwise the new tab page will appear
|
||||
after the current one. >
|
||||
:tabnew " opens tabpage after the current one
|
||||
:.tabnew " as above
|
||||
:+tabnew " opens tabpage after the next tab page
|
||||
" note: it is one further than :tabnew
|
||||
:-tabnew " opens tabpage before the current
|
||||
:0tabnew " opens tabpage before the first one
|
||||
:$tabnew " opens tabpage after the last one
|
||||
|
||||
:[count]tabe[dit] [++opt] [+cmd] {file}
|
||||
:[count]tabnew [++opt] [+cmd] {file}
|
||||
Open a new tab page and edit {file}, like with |:edit|.
|
||||
For [count] see |:tab| below.
|
||||
For [count] see |:tabnew| above.
|
||||
|
||||
:[count]tabf[ind] [++opt] [+cmd] {file} *:tabf* *:tabfind*
|
||||
Open a new tab page and edit {file} in 'path', like with
|
||||
|:find|. For [count] see |:tab| below.
|
||||
|:find|. For [count] see |:tabnew| above.
|
||||
{not available when the |+file_in_path| feature was disabled
|
||||
at compile time}
|
||||
|
||||
@ -110,12 +119,18 @@ something else.
|
||||
- When 'hidden' is not set, [!] is not used, a buffer has
|
||||
changes, and there is no other window on this buffer.
|
||||
Changes to the buffer are not written and won't get lost, so
|
||||
this is a "safe" command.
|
||||
this is a "safe" command. >
|
||||
:tabclose " close the current tab page
|
||||
|
||||
:{count}tabc[lose][!]
|
||||
:tabc[lose][!] {count}
|
||||
Close tab page {count}. Fails in the same way as `:tabclose`
|
||||
above.
|
||||
|
||||
above. >
|
||||
:-tabclose " close the previous tab page
|
||||
:+tabclose " close the next tab page
|
||||
:1tabclose " close the first tab page
|
||||
:$tabclose " close the last tab page
|
||||
<
|
||||
*:tabo* *:tabonly*
|
||||
:tabo[nly][!] Close all other tab pages.
|
||||
When the 'hidden' option is set, all buffers in closed windows
|
||||
@ -124,7 +139,16 @@ something else.
|
||||
modified buffers are written. Otherwise, windows that have
|
||||
buffers that are modified are not removed, unless the [!] is
|
||||
given, then they become hidden. But modified buffers are
|
||||
never abandoned, so changes cannot get lost.
|
||||
never abandoned, so changes cannot get lost. >
|
||||
:tabonly " close all tab pages except the current one
|
||||
|
||||
:{count}tabo[nly][!]
|
||||
Close all tab pages except the {count}th one. >
|
||||
:.tabonly " one
|
||||
:-tabonly " close all tab pages except the previous one
|
||||
:+tabonly " close all tab pages except the next one
|
||||
:1tabonly " close all tab pages except the first one
|
||||
:$tabonly " close all tab pages except the last one.
|
||||
|
||||
|
||||
SWITCHING TO ANOTHER TAB PAGE:
|
||||
@ -176,8 +200,15 @@ REORDERING TAB PAGES:
|
||||
:[N]tabm[ove]
|
||||
Move the current tab page to after tab page N. Use zero to
|
||||
make the current tab page the first one. Without N the tab
|
||||
page is made the last one.
|
||||
|
||||
page is made the last one. >
|
||||
:-tabmove " move the tab page to the left
|
||||
:tabmove " move the tab page to the right
|
||||
:.tabmove " as above
|
||||
:+tabmove " as above
|
||||
:0tabmove " move the tab page to the beginning of the tab
|
||||
" list
|
||||
:$tabmove " move the tab page to the end of the tab list
|
||||
<
|
||||
:tabm[ove] +[N]
|
||||
:tabm[ove] -[N]
|
||||
Move the current tab page N places to the right (with +) or to
|
||||
|
@ -263,28 +263,54 @@ left of the Vim window.
|
||||
Closing a window
|
||||
----------------
|
||||
|
||||
:q[uit]
|
||||
:{count}q[uit]
|
||||
CTRL-W q *CTRL-W_q*
|
||||
CTRL-W CTRL-Q *CTRL-W_CTRL-Q*
|
||||
:q[uit] Quit current window. When quitting the last window (not
|
||||
counting a help window), exit Vim.
|
||||
Without {count}: Quit the current window. If {count} is
|
||||
given quit the {count} window
|
||||
|
||||
When quitting the last window (not counting a help window),
|
||||
exit Vim.
|
||||
|
||||
When 'hidden' is set, and there is only one window for the
|
||||
current buffer, it becomes hidden.
|
||||
When 'hidden' is not set, and there is only one window for the
|
||||
current buffer, and the buffer was changed, the command fails.
|
||||
(Note: CTRL-Q does not work on all terminals)
|
||||
|
||||
:q[uit]! Quit current window. If this was the last window for a buffer,
|
||||
any changes to that buffer are lost. When quitting the last
|
||||
window (not counting help windows), exit Vim. The contents of
|
||||
the buffer are lost, even when 'hidden' is set.
|
||||
current buffer, it becomes hidden. When 'hidden' is not set,
|
||||
and there is only one window for the current buffer, and the
|
||||
buffer was changed, the command fails.
|
||||
(Note: CTRL-Q does not work on all terminals).
|
||||
If [count] is greater than the last window number the last
|
||||
window will be closed: >
|
||||
:1quit " quit the first window
|
||||
:$quit " quit the last window
|
||||
:9quit " quit the last window
|
||||
" if there are less than windows opened
|
||||
:-quit " quit the previous window
|
||||
:+quit " quit the next window
|
||||
:+2quit " will also work as expected
|
||||
<
|
||||
:q[uit]!
|
||||
:{count}q[uit]!
|
||||
Without {count}: Quit the current window. If {count} is
|
||||
given quit the {count} window
|
||||
If this was the last window for a buffer, any changes to that
|
||||
buffer are lost. When quitting the last window (not counting
|
||||
help windows), exit Vim. The contents of the buffer are lost,
|
||||
even when 'hidden' is set.
|
||||
|
||||
:clo[se][!]
|
||||
:{count}clo[se][!]
|
||||
CTRL-W c *CTRL-W_c* *:clo* *:close*
|
||||
:clo[se][!] Close current window. When the 'hidden' option is set, or
|
||||
when the buffer was changed and the [!] is used, the buffer
|
||||
becomes hidden (unless there is another window editing it).
|
||||
Without {count}: Close the current window. If given close the
|
||||
{count} window.
|
||||
|
||||
When 'hidden' is set, or when the buffer was changed and the
|
||||
[!] is used, the buffer becomes hidden (unless there is another
|
||||
window editing it).
|
||||
|
||||
When there is only one window in the current tab page and
|
||||
there is another tab page, this closes the current tab page.
|
||||
|tab-page|.
|
||||
|
||||
This command fails when: *E444*
|
||||
- There is only one window on the screen.
|
||||
- When 'hidden' is not set, [!] is not used, the buffer has
|
||||
@ -297,29 +323,38 @@ CTRL-W CTRL-C *CTRL-W_CTRL-C*
|
||||
window, but that does not work, because the CTRL-C cancels the
|
||||
command.
|
||||
|
||||
*:hide*
|
||||
:hid[e] Quit current window, unless it is the last window on the
|
||||
screen. The buffer becomes hidden (unless there is another
|
||||
window editing it or 'bufhidden' is "unload" or "delete").
|
||||
If the window is the last one in the current tab page the tab
|
||||
page is closed. |tab-page|
|
||||
*:hide*
|
||||
:hid[e]
|
||||
:{count}hid[e]
|
||||
Quit the current window, unless it is the last window on the
|
||||
screen. For {count} see |:quit|.
|
||||
|
||||
The buffer becomes hidden (unless there is another window
|
||||
editing it or 'bufhidden' is `unload` or `delete`). If the
|
||||
window is the last one in the current tab page the tab page is
|
||||
closed. |tab-page|
|
||||
|
||||
The value of 'hidden' is irrelevant for this command.
|
||||
Changes to the buffer are not written and won't get lost, so
|
||||
this is a "safe" command.
|
||||
|
||||
:hid[e] {cmd} Execute {cmd} with 'hidden' is set. The previous value of
|
||||
:hid[e] {cmd} Execute {cmd} with 'hidden' set. The previous value of
|
||||
'hidden' is restored after {cmd} has been executed.
|
||||
Example: >
|
||||
:hide edit Makefile
|
||||
< This will edit "Makefile", and hide the current buffer if it
|
||||
has any changes.
|
||||
|
||||
:on[ly][!]
|
||||
:{count}on[ly][!]
|
||||
CTRL-W o *CTRL-W_o* *E445*
|
||||
CTRL-W CTRL-O *CTRL-W_CTRL-O* *:on* *:only*
|
||||
:on[ly][!] Make the current window the only one on the screen. All other
|
||||
windows are closed.
|
||||
Make the current window the only one on the screen. All other
|
||||
windows are closed. For {count} see |:quit|.
|
||||
|
||||
When the 'hidden' option is set, all buffers in closed windows
|
||||
become hidden.
|
||||
|
||||
When 'hidden' is not set, and the 'autowrite' option is set,
|
||||
modified buffers are written. Otherwise, windows that have
|
||||
buffers that are modified are not removed, unless the [!] is
|
||||
|
@ -67,8 +67,9 @@ for i, cmd in ipairs(defs) do
|
||||
[%s] = {
|
||||
.cmd_name = (char_u *) "%s",
|
||||
.cmd_func = &%s,
|
||||
.cmd_argt = %u
|
||||
}]], enumname, cmd.command, cmd.func, cmd.flags))
|
||||
.cmd_argt = %uL,
|
||||
.cmd_addr_type = %i
|
||||
}]], enumname, cmd.command, cmd.func, cmd.flags, cmd.addr_type))
|
||||
end
|
||||
defsfile:write([[
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -71,6 +71,14 @@
|
||||
#define WORD1 (EXTRA | NOSPC) /* one extra word allowed */
|
||||
#define FILE1 (FILES | NOSPC) /* 1 file allowed, defaults to current file */
|
||||
|
||||
// values for cmd_addr_type
|
||||
#define ADDR_LINES 0
|
||||
#define ADDR_WINDOWS 1
|
||||
#define ADDR_ARGUMENTS 2
|
||||
#define ADDR_LOADED_BUFFERS 3
|
||||
#define ADDR_UNLOADED_BUFFERS 4
|
||||
#define ADDR_TABS 5
|
||||
|
||||
typedef struct exarg exarg_T;
|
||||
|
||||
/* behavior for bad character, "++bad=" argument */
|
||||
@ -87,6 +95,7 @@ typedef struct cmdname {
|
||||
char_u *cmd_name; ///< Name of the command.
|
||||
ex_func_T cmd_func; ///< Function with implementation of this command.
|
||||
uint32_t cmd_argt; ///< Relevant flags from the declared above.
|
||||
int cmd_addr_type; ///< Flag for address type
|
||||
} CommandDefinition;
|
||||
|
||||
/// Arguments used for Ex commands.
|
||||
@ -102,6 +111,7 @@ struct exarg {
|
||||
int addr_count; ///< the number of addresses given
|
||||
linenr_T line1; ///< the first line number
|
||||
linenr_T line2; ///< the second line number or count
|
||||
int addr_type; ///< type of the count/range
|
||||
int flags; ///< extra flags after count: EXFLAG_
|
||||
char_u *do_ecmd_cmd; ///< +command arg to be used in edited file
|
||||
linenr_T do_ecmd_lnum; ///< the line number in an edited file
|
||||
|
@ -1065,6 +1065,33 @@ void * getline_cookie(LineGetter fgetline,
|
||||
return cp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper function to apply an offset for buffer commands, i.e. ":bdelete",
|
||||
* ":bwipeout", etc.
|
||||
* Returns the buffer number.
|
||||
*/
|
||||
static int compute_buffer_local_count(int addr_type, int lnum, int offset)
|
||||
{
|
||||
buf_T *buf;
|
||||
int count = offset;
|
||||
|
||||
buf = firstbuf;
|
||||
while (buf->b_next != NULL && buf->b_fnum < lnum)
|
||||
buf = buf->b_next;
|
||||
while (count != 0) {
|
||||
count += (count < 0) ? 1 : -1;
|
||||
if (buf->b_prev == NULL)
|
||||
break;
|
||||
buf = (count < 0) ? buf->b_prev : buf->b_next;
|
||||
if (addr_type == ADDR_LOADED_BUFFERS)
|
||||
/* skip over unloaded buffers */
|
||||
while (buf->b_prev != NULL && buf->b_ml.ml_mfp == NULL) {
|
||||
buf = (count < 0) ? buf->b_prev : buf->b_next;
|
||||
}
|
||||
}
|
||||
return buf->b_fnum;
|
||||
}
|
||||
|
||||
/*
|
||||
* Execute one Ex command.
|
||||
*
|
||||
@ -1072,10 +1099,11 @@ void * getline_cookie(LineGetter fgetline,
|
||||
*
|
||||
* 1. skip comment lines and leading space
|
||||
* 2. handle command modifiers
|
||||
* 3. parse range
|
||||
* 4. parse command
|
||||
* 5. parse arguments
|
||||
* 6. switch on command name
|
||||
* 3. skip over the range to find the command
|
||||
* 4. parse the range
|
||||
* 5. parse the command
|
||||
* 6. parse arguments
|
||||
* 7. switch on command name
|
||||
*
|
||||
* Note: "fgetline" can be NULL.
|
||||
*
|
||||
@ -1100,6 +1128,9 @@ static char_u * do_one_cmd(char_u **cmdlinep,
|
||||
int did_sandbox = FALSE;
|
||||
cmdmod_T save_cmdmod;
|
||||
int ni; /* set when Not Implemented */
|
||||
win_T *wp;
|
||||
tabpage_T *tp;
|
||||
char_u *cmd;
|
||||
|
||||
memset(&ea, 0, sizeof(ea));
|
||||
ea.line1 = 1;
|
||||
@ -1132,7 +1163,7 @@ static char_u * do_one_cmd(char_u **cmdlinep,
|
||||
ea.cmd = *cmdlinep;
|
||||
for (;; ) {
|
||||
/*
|
||||
* 1. skip comment lines and leading white space and colons
|
||||
* 1. Skip comment lines and leading white space and colons.
|
||||
*/
|
||||
while (*ea.cmd == ' ' || *ea.cmd == '\t' || *ea.cmd == ':')
|
||||
++ea.cmd;
|
||||
@ -1155,7 +1186,7 @@ static char_u * do_one_cmd(char_u **cmdlinep,
|
||||
}
|
||||
|
||||
/*
|
||||
* 2. handle command modifiers.
|
||||
* 2. Handle command modifiers.
|
||||
*/
|
||||
p = ea.cmd;
|
||||
if (ascii_isdigit(*ea.cmd))
|
||||
@ -1319,8 +1350,18 @@ static char_u * do_one_cmd(char_u **cmdlinep,
|
||||
(void)do_intthrow(cstack);
|
||||
}
|
||||
|
||||
// 3. Skip over the range to find the command. Let "p" point to after it.
|
||||
//
|
||||
// We need the command to know what kind of range it uses.
|
||||
|
||||
cmd = ea.cmd;
|
||||
ea.cmd = skip_range(ea.cmd, NULL);
|
||||
if (*ea.cmd == '*' && vim_strchr(p_cpo, CPO_STAR) == NULL)
|
||||
ea.cmd = skipwhite(ea.cmd + 1);
|
||||
p = find_command(&ea, NULL);
|
||||
|
||||
/*
|
||||
* 3. parse a range specifier of the form: addr [,addr] [;addr] ..
|
||||
* 4. Parse a range specifier of the form: addr [,addr] [;addr] ..
|
||||
*
|
||||
* where 'addr' is:
|
||||
*
|
||||
@ -1336,25 +1377,82 @@ static char_u * do_one_cmd(char_u **cmdlinep,
|
||||
* is equal to the lower.
|
||||
*/
|
||||
|
||||
if (ea.cmdidx != CMD_SIZE) {
|
||||
ea.addr_type = cmdnames[(int)ea.cmdidx].cmd_addr_type;
|
||||
} else {
|
||||
ea.addr_type = ADDR_LINES;
|
||||
}
|
||||
ea.cmd = cmd;
|
||||
|
||||
/* repeat for all ',' or ';' separated addresses */
|
||||
for (;; ) {
|
||||
ea.line1 = ea.line2;
|
||||
ea.line2 = curwin->w_cursor.lnum; /* default is current line number */
|
||||
switch (ea.addr_type) {
|
||||
case ADDR_LINES:
|
||||
// default is current line number
|
||||
ea.line2 = curwin->w_cursor.lnum;
|
||||
break;
|
||||
case ADDR_WINDOWS:
|
||||
lnum = 0;
|
||||
for (wp = firstwin; wp != NULL; wp = wp->w_next) {
|
||||
lnum++;
|
||||
if (wp == curwin)
|
||||
break;
|
||||
}
|
||||
ea.line2 = lnum;
|
||||
break;
|
||||
case ADDR_ARGUMENTS:
|
||||
ea.line2 = curwin->w_arg_idx + 1;
|
||||
break;
|
||||
case ADDR_LOADED_BUFFERS:
|
||||
case ADDR_UNLOADED_BUFFERS:
|
||||
ea.line2 = curbuf->b_fnum;
|
||||
break;
|
||||
case ADDR_TABS:
|
||||
lnum = 0;
|
||||
for (tp = first_tabpage; tp != NULL; tp = tp->tp_next) {
|
||||
lnum++;
|
||||
if (tp == curtab)
|
||||
break;
|
||||
}
|
||||
ea.line2 = lnum;
|
||||
break;
|
||||
}
|
||||
ea.cmd = skipwhite(ea.cmd);
|
||||
lnum = get_address(&ea.cmd, ea.skip, ea.addr_count == 0);
|
||||
lnum = get_address(&ea.cmd, ea.addr_type, ea.skip, ea.addr_count == 0);
|
||||
if (ea.cmd == NULL) /* error detected */
|
||||
goto doend;
|
||||
if (lnum == MAXLNUM) {
|
||||
if (*ea.cmd == '%') { /* '%' - all lines */
|
||||
++ea.cmd;
|
||||
ea.line1 = 1;
|
||||
ea.line2 = curbuf->b_ml.ml_line_count;
|
||||
switch (ea.addr_type) {
|
||||
case ADDR_LINES:
|
||||
ea.line1 = 1;
|
||||
ea.line2 = curbuf->b_ml.ml_line_count;
|
||||
break;
|
||||
case ADDR_WINDOWS:
|
||||
case ADDR_LOADED_BUFFERS:
|
||||
case ADDR_UNLOADED_BUFFERS:
|
||||
case ADDR_TABS:
|
||||
errormsg = (char_u *)_(e_invrange);
|
||||
goto doend;
|
||||
break;
|
||||
case ADDR_ARGUMENTS:
|
||||
ea.line1 = 1;
|
||||
ea.line2 = ARGCOUNT;
|
||||
break;
|
||||
}
|
||||
++ea.addr_count;
|
||||
}
|
||||
/* '*' - visual area */
|
||||
else if (*ea.cmd == '*' && vim_strchr(p_cpo, CPO_STAR) == NULL) {
|
||||
pos_T *fp;
|
||||
|
||||
if (ea.addr_type != ADDR_LINES) {
|
||||
errormsg = (char_u *)_(e_invrange);
|
||||
goto doend;
|
||||
}
|
||||
|
||||
++ea.cmd;
|
||||
if (!ea.skip) {
|
||||
fp = getmark('<', FALSE);
|
||||
@ -1392,7 +1490,7 @@ static char_u * do_one_cmd(char_u **cmdlinep,
|
||||
check_cursor_lnum();
|
||||
|
||||
/*
|
||||
* 4. parse command
|
||||
* 5. Parse the command.
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -1446,9 +1544,6 @@ static char_u * do_one_cmd(char_u **cmdlinep,
|
||||
goto doend;
|
||||
}
|
||||
|
||||
/* Find the command and let "p" point to after it. */
|
||||
p = find_command(&ea, NULL);
|
||||
|
||||
// If this looks like an undefined user command and there are CmdUndefined
|
||||
// autocommands defined, trigger the matching autocommands.
|
||||
if (p != NULL && ea.cmdidx == CMD_SIZE && !ea.skip
|
||||
@ -1502,7 +1597,7 @@ static char_u * do_one_cmd(char_u **cmdlinep,
|
||||
ea.forceit = FALSE;
|
||||
|
||||
/*
|
||||
* 5. parse arguments
|
||||
* 6. Parse arguments.
|
||||
*/
|
||||
if (!IS_USER_CMDIDX(ea.cmdidx)) {
|
||||
ea.argt = cmdnames[(int)ea.cmdidx].cmd_argt;
|
||||
@ -1888,7 +1983,7 @@ static char_u * do_one_cmd(char_u **cmdlinep,
|
||||
}
|
||||
|
||||
/*
|
||||
* 6. switch on command name
|
||||
* 7. Switch on command name.
|
||||
*
|
||||
* The "ea" structure holds the arguments that can be used.
|
||||
*/
|
||||
@ -3098,12 +3193,11 @@ skip_range (
|
||||
*
|
||||
* Return MAXLNUM when no Ex address was found.
|
||||
*/
|
||||
static linenr_T
|
||||
get_address (
|
||||
char_u **ptr,
|
||||
int skip, /* only skip the address, don't use it */
|
||||
int to_other_file /* flag: may jump to other file */
|
||||
)
|
||||
static linenr_T get_address(char_u **ptr,
|
||||
int addr_type, // flag: one of ADDR_LINES, ...
|
||||
int skip, // only skip the address, don't use it
|
||||
int to_other_file // flag: may jump to other file
|
||||
)
|
||||
{
|
||||
int c;
|
||||
int i;
|
||||
@ -3112,6 +3206,9 @@ get_address (
|
||||
pos_T pos;
|
||||
pos_T *fp;
|
||||
linenr_T lnum;
|
||||
win_T *wp;
|
||||
tabpage_T *tp;
|
||||
buf_T *buf;
|
||||
|
||||
cmd = skipwhite(*ptr);
|
||||
lnum = MAXLNUM;
|
||||
@ -3119,12 +3216,68 @@ get_address (
|
||||
switch (*cmd) {
|
||||
case '.': /* '.' - Cursor position */
|
||||
++cmd;
|
||||
lnum = curwin->w_cursor.lnum;
|
||||
switch (addr_type) {
|
||||
case ADDR_LINES:
|
||||
lnum = curwin->w_cursor.lnum;
|
||||
break;
|
||||
case ADDR_WINDOWS:
|
||||
lnum = 0;
|
||||
for (wp = firstwin; wp != NULL; wp = wp->w_next) {
|
||||
lnum++;
|
||||
if (wp == curwin)
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case ADDR_ARGUMENTS:
|
||||
lnum = curwin->w_arg_idx + 1;
|
||||
break;
|
||||
case ADDR_LOADED_BUFFERS:
|
||||
case ADDR_UNLOADED_BUFFERS:
|
||||
lnum = curbuf->b_fnum;
|
||||
for (tp = first_tabpage; tp != NULL; tp = tp->tp_next) {
|
||||
lnum++;
|
||||
if (tp == curtab)
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case '$': /* '$' - last line */
|
||||
++cmd;
|
||||
lnum = curbuf->b_ml.ml_line_count;
|
||||
switch (addr_type) {
|
||||
case ADDR_LINES:
|
||||
lnum = curbuf->b_ml.ml_line_count;
|
||||
break;
|
||||
case ADDR_WINDOWS:
|
||||
lnum = 0;
|
||||
for (wp = firstwin; wp != NULL; wp = wp->w_next) {
|
||||
lnum++;
|
||||
}
|
||||
break;
|
||||
case ADDR_ARGUMENTS:
|
||||
lnum = ARGCOUNT;
|
||||
break;
|
||||
case ADDR_LOADED_BUFFERS:
|
||||
buf = lastbuf;
|
||||
while (buf->b_ml.ml_mfp == NULL) {
|
||||
if (buf->b_prev == NULL) {
|
||||
break;
|
||||
}
|
||||
buf = buf->b_prev;
|
||||
}
|
||||
lnum = buf->b_fnum;
|
||||
break;
|
||||
case ADDR_UNLOADED_BUFFERS:
|
||||
lnum = lastbuf->b_fnum;
|
||||
break;
|
||||
case ADDR_TABS:
|
||||
lnum = 0;
|
||||
for (tp = first_tabpage; tp != NULL; tp = tp->tp_next) {
|
||||
lnum++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case '\'': /* ''' - mark */
|
||||
@ -3132,6 +3285,10 @@ get_address (
|
||||
cmd = NULL;
|
||||
goto error;
|
||||
}
|
||||
if (addr_type != ADDR_LINES) {
|
||||
EMSG(_(e_invaddr));
|
||||
goto error;
|
||||
}
|
||||
if (skip)
|
||||
++cmd;
|
||||
else {
|
||||
@ -3155,6 +3312,10 @@ get_address (
|
||||
case '/':
|
||||
case '?': /* '/' or '?' - search */
|
||||
c = *cmd++;
|
||||
if (addr_type != ADDR_LINES) {
|
||||
EMSG(_(e_invaddr));
|
||||
goto error;
|
||||
}
|
||||
if (skip) { /* skip "/pat/" */
|
||||
cmd = skip_regexp(cmd, c, p_magic, NULL);
|
||||
if (*cmd == c)
|
||||
@ -3194,6 +3355,10 @@ get_address (
|
||||
|
||||
case '\\': /* "\?", "\/" or "\&", repeat search */
|
||||
++cmd;
|
||||
if (addr_type != ADDR_LINES) {
|
||||
EMSG(_(e_invaddr));
|
||||
goto error;
|
||||
}
|
||||
if (*cmd == '&')
|
||||
i = RE_SUBST;
|
||||
else if (*cmd == '?' || *cmd == '/')
|
||||
@ -3233,8 +3398,37 @@ get_address (
|
||||
if (*cmd != '-' && *cmd != '+' && !ascii_isdigit(*cmd))
|
||||
break;
|
||||
|
||||
if (lnum == MAXLNUM)
|
||||
lnum = curwin->w_cursor.lnum; /* "+1" is same as ".+1" */
|
||||
if (lnum == MAXLNUM) {
|
||||
switch (addr_type) {
|
||||
case ADDR_LINES:
|
||||
lnum = curwin->w_cursor.lnum; /* "+1" is same as ".+1" */
|
||||
break;
|
||||
case ADDR_WINDOWS:
|
||||
lnum = 0;
|
||||
for (wp = firstwin; wp != NULL; wp = wp->w_next) {
|
||||
lnum++;
|
||||
if (wp == curwin)
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case ADDR_ARGUMENTS:
|
||||
lnum = curwin->w_arg_idx + 1;
|
||||
break;
|
||||
case ADDR_LOADED_BUFFERS:
|
||||
case ADDR_UNLOADED_BUFFERS:
|
||||
lnum = curbuf->b_fnum;
|
||||
break;
|
||||
case ADDR_TABS:
|
||||
lnum = 0;
|
||||
for (tp = first_tabpage; tp != NULL; tp = tp->tp_next) {
|
||||
lnum++;
|
||||
if (tp == curtab)
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ascii_isdigit(*cmd))
|
||||
i = '+'; /* "number" is same as "+number" */
|
||||
else
|
||||
@ -3242,11 +3436,56 @@ get_address (
|
||||
if (!ascii_isdigit(*cmd)) /* '+' is '+1', but '+0' is not '+1' */
|
||||
n = 1;
|
||||
else
|
||||
n = getdigits_long(&cmd);
|
||||
if (i == '-')
|
||||
n = getdigits(&cmd);
|
||||
if (addr_type == ADDR_LOADED_BUFFERS ||
|
||||
addr_type == ADDR_UNLOADED_BUFFERS)
|
||||
lnum = compute_buffer_local_count(addr_type, lnum, n);
|
||||
else if (i == '-')
|
||||
lnum -= n;
|
||||
else
|
||||
lnum += n;
|
||||
|
||||
switch (addr_type) {
|
||||
case ADDR_LINES:
|
||||
break;
|
||||
case ADDR_ARGUMENTS:
|
||||
if (lnum < 0)
|
||||
lnum = 0;
|
||||
else if (lnum >= ARGCOUNT)
|
||||
lnum = ARGCOUNT;
|
||||
break;
|
||||
case ADDR_TABS:
|
||||
if (lnum < 0) {
|
||||
lnum = 0;
|
||||
break;
|
||||
}
|
||||
c = 0;
|
||||
for (tp = first_tabpage; tp != NULL; tp = tp->tp_next)
|
||||
c++;
|
||||
if (lnum >= c)
|
||||
lnum = c;
|
||||
break;
|
||||
case ADDR_WINDOWS:
|
||||
if (lnum < 0) {
|
||||
lnum = 0;
|
||||
break;
|
||||
}
|
||||
c = 0;
|
||||
for (wp = firstwin; wp != NULL; wp = wp->w_next)
|
||||
c++;
|
||||
if (lnum > c)
|
||||
lnum = c;
|
||||
break;
|
||||
case ADDR_LOADED_BUFFERS:
|
||||
case ADDR_UNLOADED_BUFFERS:
|
||||
if (lnum < firstbuf->b_fnum) {
|
||||
lnum = firstbuf->b_fnum;
|
||||
break;
|
||||
}
|
||||
if (lnum > lastbuf->b_fnum)
|
||||
lnum = lastbuf->b_fnum;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while (*cmd == '/' || *cmd == '?');
|
||||
|
||||
@ -5102,10 +5341,29 @@ static void ex_quit(exarg_T *eap)
|
||||
text_locked_msg();
|
||||
return;
|
||||
}
|
||||
|
||||
win_T *wp;
|
||||
buf_T *buf;
|
||||
int wnr;
|
||||
|
||||
if (eap->addr_count > 0) {
|
||||
wnr = eap->line2;
|
||||
for (wp = firstwin; --wnr > 0;) {
|
||||
if (wp->w_next == NULL)
|
||||
break;
|
||||
else
|
||||
wp = wp->w_next;
|
||||
}
|
||||
buf = wp->w_buffer;
|
||||
} else {
|
||||
wp = curwin;
|
||||
buf = curbuf;
|
||||
}
|
||||
|
||||
apply_autocmds(EVENT_QUITPRE, NULL, NULL, FALSE, curbuf);
|
||||
/* Refuse to quit when locked or when the buffer in the last window is
|
||||
* being closed (can only happen in autocommands). */
|
||||
if (curbuf_locked() || (curbuf->b_nwindows == 1 && curbuf->b_closing))
|
||||
if (curbuf_locked() || (buf->b_nwindows == 1 && curbuf->b_closing))
|
||||
return;
|
||||
|
||||
|
||||
@ -5127,7 +5385,7 @@ static void ex_quit(exarg_T *eap)
|
||||
getout(0);
|
||||
}
|
||||
/* close window; may free buffer */
|
||||
win_close(curwin, !P_HID(curwin->w_buffer) || eap->forceit);
|
||||
win_close(wp, !P_HID(wp->w_buffer) || eap->forceit);
|
||||
}
|
||||
}
|
||||
|
||||
@ -5174,12 +5432,24 @@ static void ex_quit_all(exarg_T *eap)
|
||||
*/
|
||||
static void ex_close(exarg_T *eap)
|
||||
{
|
||||
win_T *win;
|
||||
int winnr = 0;
|
||||
if (cmdwin_type != 0)
|
||||
cmdwin_result = Ctrl_C;
|
||||
else if (!text_locked()
|
||||
&& !curbuf_locked()
|
||||
)
|
||||
ex_win_close(eap->forceit, curwin, NULL);
|
||||
else if (!text_locked() && !curbuf_locked()) {
|
||||
if (eap->addr_count == 0)
|
||||
ex_win_close(eap->forceit, curwin, NULL);
|
||||
else {
|
||||
for (win = firstwin; win != NULL; win = win->w_next) {
|
||||
winnr++;
|
||||
if (winnr == eap->line2)
|
||||
break;
|
||||
}
|
||||
if (win == NULL)
|
||||
win = lastwin;
|
||||
ex_win_close(eap->forceit, win, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -5271,6 +5541,8 @@ static void ex_tabonly(exarg_T *eap)
|
||||
else if (first_tabpage->tp_next == NULL)
|
||||
MSG(_("Already only one tab page"));
|
||||
else {
|
||||
if (eap->addr_count > 0)
|
||||
goto_tabpage(eap->line2);
|
||||
/* Repeat this up to a 1000 times, because autocommands may mess
|
||||
* up the lists. */
|
||||
for (int done = 0; done < 1000; ++done) {
|
||||
@ -5341,6 +5613,18 @@ void tabpage_close_other(tabpage_T *tp, int forceit)
|
||||
*/
|
||||
static void ex_only(exarg_T *eap)
|
||||
{
|
||||
win_T *wp;
|
||||
int wnr;
|
||||
if (eap->addr_count > 0) {
|
||||
wnr = eap->line2;
|
||||
for (wp = firstwin; --wnr > 0;) {
|
||||
if (wp->w_next == NULL)
|
||||
break;
|
||||
else
|
||||
wp = wp->w_next;
|
||||
}
|
||||
win_goto(wp);
|
||||
}
|
||||
close_others(TRUE, eap->forceit);
|
||||
}
|
||||
|
||||
@ -5357,13 +5641,26 @@ void ex_all(exarg_T *eap)
|
||||
|
||||
static void ex_hide(exarg_T *eap)
|
||||
{
|
||||
win_T *win;
|
||||
int winnr = 0;
|
||||
if (*eap->arg != NUL && check_nextcmd(eap->arg) == NULL)
|
||||
eap->errmsg = e_invarg;
|
||||
else {
|
||||
/* ":hide" or ":hide | cmd": hide current window */
|
||||
eap->nextcmd = check_nextcmd(eap->arg);
|
||||
if (!eap->skip) {
|
||||
win_close(curwin, FALSE); /* don't free buffer */
|
||||
if (eap->addr_count == 0)
|
||||
win_close(curwin, FALSE); /* don't free buffer */
|
||||
else {
|
||||
for (win = firstwin; win != NULL; win = win->w_next) {
|
||||
winnr++;
|
||||
if (winnr == eap->line2)
|
||||
break;
|
||||
}
|
||||
if (win == NULL)
|
||||
win = lastwin;
|
||||
win_close(win, FALSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -6518,7 +6815,7 @@ static void ex_copymove(exarg_T *eap)
|
||||
{
|
||||
long n;
|
||||
|
||||
n = get_address(&eap->arg, FALSE, FALSE);
|
||||
n = get_address(&eap->arg, eap->addr_type, FALSE, FALSE);
|
||||
if (eap->arg == NULL) { /* error detected */
|
||||
eap->nextcmd = NULL;
|
||||
return;
|
||||
|
@ -29,7 +29,9 @@ SCRIPTS := test_autoformat_join.out \
|
||||
test86.out test87.out test88.out \
|
||||
test96.out \
|
||||
test_listlbr.out \
|
||||
test_breakindent.out
|
||||
test_breakindent.out \
|
||||
test_argument_count.out \
|
||||
test_close_count.out
|
||||
|
||||
SCRIPTS_GUI := test16.out
|
||||
|
||||
|
47
src/nvim/testdir/test_argument_count.in
Normal file
47
src/nvim/testdir/test_argument_count.in
Normal file
@ -0,0 +1,47 @@
|
||||
Tests for :[count]argument! and :[count]argdelete vim: set ft=vim :
|
||||
|
||||
STARTTEST
|
||||
:%argd
|
||||
:argadd a b c d
|
||||
:set hidden
|
||||
:let buffers = []
|
||||
:augroup TEST
|
||||
:au BufEnter * call add(buffers, expand('%:t'))
|
||||
:augroup END
|
||||
:$argu
|
||||
:$-argu
|
||||
:-argu
|
||||
:1argu
|
||||
:+2argu
|
||||
:augroup TEST
|
||||
:au!
|
||||
:augroup END
|
||||
:let arglists = []
|
||||
:.argd
|
||||
:call add(arglists, argv())
|
||||
:-argd
|
||||
:call add(arglists, argv())
|
||||
:$argd
|
||||
:call add(arglists, argv())
|
||||
:1arga c
|
||||
:1arga b
|
||||
:$argu
|
||||
:+arga d
|
||||
:$arga x
|
||||
:call add(arglists, argv())
|
||||
:$-10arga Y
|
||||
:call add(arglists, argv())
|
||||
:%argd
|
||||
:call add(arglists, argv())
|
||||
:arga a b c d e f
|
||||
:2,$-argd
|
||||
:call add(arglists, argv())
|
||||
:e! test.out
|
||||
:call append(0, buffers)
|
||||
:let lnr = line('$')
|
||||
:call append(lnr, map(copy(arglists), 'join(v:val, " ")'))
|
||||
:w
|
||||
:qa!
|
||||
ENDTEST
|
||||
|
||||
|
13
src/nvim/testdir/test_argument_count.ok
Normal file
13
src/nvim/testdir/test_argument_count.ok
Normal file
@ -0,0 +1,13 @@
|
||||
d
|
||||
c
|
||||
b
|
||||
a
|
||||
c
|
||||
|
||||
a b d
|
||||
a d
|
||||
a
|
||||
a b c d x
|
||||
Y a b c d x
|
||||
|
||||
a f
|
156
src/nvim/testdir/test_close_count.in
Normal file
156
src/nvim/testdir/test_close_count.in
Normal file
@ -0,0 +1,156 @@
|
||||
Tests for :[count]close! and :[count]hide vim: set ft=vim :
|
||||
|
||||
STARTTEST
|
||||
:let tests = []
|
||||
:so tiny.vim
|
||||
:for i in range(5)
|
||||
:new
|
||||
:endfor
|
||||
:4wincmd w
|
||||
:close!
|
||||
:let buffers = []
|
||||
:windo call add(buffers, bufnr('%'))
|
||||
:call add(tests, buffers)
|
||||
:1close!
|
||||
:let buffers = []
|
||||
:windo call add(buffers, bufnr('%'))
|
||||
:call add(tests, buffers)
|
||||
:$close!
|
||||
:let buffers = []
|
||||
:windo call add(buffers, bufnr('%'))
|
||||
:call add(tests, buffers)
|
||||
:1wincmd w
|
||||
:2close!
|
||||
:let buffers = []
|
||||
:windo call add(buffers, bufnr('%'))
|
||||
:call add(tests, buffers)
|
||||
:1wincmd w
|
||||
:new
|
||||
:new
|
||||
:2wincmd w
|
||||
:-2close!
|
||||
:let buffers = []
|
||||
:windo call add(buffers, bufnr('%'))
|
||||
:call add(tests, buffers)
|
||||
:2wincmd w
|
||||
:+1close!
|
||||
:let buffers = []
|
||||
:windo call add(buffers, bufnr('%'))
|
||||
:call add(tests, buffers)
|
||||
:e! test.out
|
||||
:call append(0, map(copy(tests), 'join(v:val, " ")'))
|
||||
:w
|
||||
:only!
|
||||
:b1
|
||||
ENDTEST
|
||||
|
||||
STARTTEST
|
||||
:let tests = []
|
||||
:so tiny.vim
|
||||
:for i in range(5)
|
||||
:new
|
||||
:endfor
|
||||
:let buffers = []
|
||||
:windo call add(buffers, bufnr('%'))
|
||||
:call add(tests, buffers)
|
||||
:4wincmd w
|
||||
:.hide
|
||||
:let buffers = []
|
||||
:windo call add(buffers, bufnr('%'))
|
||||
:call add(tests, buffers)
|
||||
:1hide
|
||||
:let buffers = []
|
||||
:windo call add(buffers, bufnr('%'))
|
||||
:call add(tests, buffers)
|
||||
:9hide
|
||||
:let buffers = []
|
||||
:windo call add(buffers, bufnr('%'))
|
||||
:call add(tests, buffers)
|
||||
:1wincmd w
|
||||
:2hide
|
||||
:let buffers = []
|
||||
:windo call add(buffers, bufnr('%'))
|
||||
:call add(tests, buffers)
|
||||
:1wincmd w
|
||||
:new
|
||||
:new
|
||||
:3wincmd w
|
||||
:-hide
|
||||
:let buffers = []
|
||||
:windo call add(buffers, bufnr('%'))
|
||||
:call add(tests, buffers)
|
||||
:2wincmd w
|
||||
:+hide
|
||||
:let buffers = []
|
||||
:windo call add(buffers, bufnr('%'))
|
||||
:call add(tests, buffers)
|
||||
:e! test.out
|
||||
:call append(line('$'), map(copy(tests), 'join(v:val, " ")'))
|
||||
Go
|
||||
:w
|
||||
:only!
|
||||
:b1
|
||||
ENDTEST
|
||||
|
||||
STARTTEST
|
||||
:let tests = []
|
||||
:so tiny.vim
|
||||
:set hidden
|
||||
:for i in range(5)
|
||||
:new
|
||||
:endfor
|
||||
:1wincmd w
|
||||
:$ hide
|
||||
:let buffers = []
|
||||
:windo call add(buffers, bufnr('%'))
|
||||
:call add(tests, buffers)
|
||||
:$-1 close!
|
||||
:let buffers = []
|
||||
:windo call add(buffers, bufnr('%'))
|
||||
:call add(tests, buffers)
|
||||
:1wincmd w
|
||||
:.+close!
|
||||
:let buffers = []
|
||||
:windo call add(buffers, bufnr('%'))
|
||||
:call add(tests, buffers)
|
||||
:e! test.out
|
||||
:call append(line('$'), map(copy(tests), 'join(v:val, " ")'))
|
||||
Go
|
||||
:w
|
||||
:only!
|
||||
:b1
|
||||
ENDTEST
|
||||
|
||||
STARTTEST
|
||||
:let tests = []
|
||||
:so tiny.vim
|
||||
:set hidden
|
||||
:for i in range(5)
|
||||
:new
|
||||
:endfor
|
||||
:4wincmd w
|
||||
c
|
||||
:let buffers = []
|
||||
:windo call add(buffers, bufnr('%'))
|
||||
:call add(tests, buffers)
|
||||
1c
|
||||
:let buffers = []
|
||||
:windo call add(buffers, bufnr('%'))
|
||||
:call add(tests, buffers)
|
||||
9c
|
||||
:let buffers = []
|
||||
:windo call add(buffers, bufnr('%'))
|
||||
:call add(tests, buffers)
|
||||
:1wincmd w
|
||||
2c
|
||||
:let buffers = []
|
||||
:windo call add(buffers, bufnr('%'))
|
||||
:call add(tests, buffers)
|
||||
:only!
|
||||
:e! test.out
|
||||
:call append(line('$'), map(copy(tests), 'join(v:val, " ")'))
|
||||
:w
|
||||
:qa!
|
||||
ENDTEST
|
||||
|
||||
|
23
src/nvim/testdir/test_close_count.ok
Normal file
23
src/nvim/testdir/test_close_count.ok
Normal file
@ -0,0 +1,23 @@
|
||||
6 5 4 2 1
|
||||
5 4 2 1
|
||||
5 4 2
|
||||
5 2
|
||||
7 5 2
|
||||
7 5
|
||||
|
||||
13 12 11 10 9 1
|
||||
13 12 11 9 1
|
||||
12 11 9 1
|
||||
12 11 9
|
||||
12 9
|
||||
15 12 9
|
||||
15 12
|
||||
|
||||
20 19 18 17 16
|
||||
20 19 18 16
|
||||
20 18 16
|
||||
|
||||
25 24 23 21 1
|
||||
24 23 21 1
|
||||
24 23 21
|
||||
24 21
|
@ -151,14 +151,20 @@ newwindow:
|
||||
case Ctrl_Q:
|
||||
case 'q':
|
||||
reset_VIsual_and_resel(); /* stop Visual mode */
|
||||
do_cmdline_cmd((char_u *)"quit");
|
||||
STRCPY(cbuf, "quit");
|
||||
if (Prenum)
|
||||
vim_snprintf((char *)cbuf + 4, sizeof(cbuf) - 5, "%ld", Prenum);
|
||||
do_cmdline_cmd(cbuf);
|
||||
break;
|
||||
|
||||
/* close current window */
|
||||
case Ctrl_C:
|
||||
case 'c':
|
||||
reset_VIsual_and_resel(); /* stop Visual mode */
|
||||
do_cmdline_cmd((char_u *)"close");
|
||||
STRCPY(cbuf, "close");
|
||||
if (Prenum)
|
||||
vim_snprintf((char *)cbuf + 4, sizeof(cbuf) - 5, "%ld", Prenum);
|
||||
do_cmdline_cmd(cbuf);
|
||||
break;
|
||||
|
||||
/* close preview window */
|
||||
@ -183,7 +189,10 @@ newwindow:
|
||||
case Ctrl_O:
|
||||
case 'o':
|
||||
CHECK_CMDWIN reset_VIsual_and_resel(); /* stop Visual mode */
|
||||
do_cmdline_cmd((char_u *)"only");
|
||||
STRCPY(cbuf, "only");
|
||||
if (Prenum > 0)
|
||||
vim_snprintf((char *)cbuf + 4, sizeof(cbuf) - 4, "%ld", Prenum);
|
||||
do_cmdline_cmd(cbuf);
|
||||
break;
|
||||
|
||||
/* cursor to next window with wrap around */
|
||||
|
Loading…
Reference in New Issue
Block a user