On 20:02 Thu 21 Aug , Christian Brabandt wrote: > > On Do, 21 Aug 2014, 'Andy Wokula' via vim_dev wrote: > > > Am 21.08.2014 um 07:49 schrieb Christian Brabandt: > > >Am 2014-08-20 19:03, schrieb 'Andy Wokula' via vim_dev: > > >>Some people expect :1,$bd or :%bd to delete all buffers. > > > > > >That only works by accident, because your current buffer has more > > >lines than you have open buffers. > > > > > >Or saying it differently, this does not work in an empty buffer. > > > > > >So this expectation is not really valid. > > > > Er, what you cited implies that it doesn't work at the moment > > (as expected (by some people (for a long time))). > > > > The idea is to make it become valid ... > > > > >Marcin Szamotulski wrote: > > >>There are probably a few other commands that could benefit with a > > >>similar approach. > > > > Got it? > > > > Ah, I thought you wanted to keep the current behaviour, that currently > %bd already does delete all buffers (but only, if your buffer has enough > lines). > > Best, > Christian > -- > Richtiges Auffassen einer Sache und Mißverstehen der gleichen Sache > schließen einander nicht aus. > -- Franz Kafka >
Hi, So here are updated patches: count.patch - the counts argadd.patch - :argadd to be a valid command without and argument (:argadd%) Best regards, Marcin
diff -r b9ec5ed29480 -r b95122e84f81 src/ex_cmds.h
--- a/src/ex_cmds.h Thu Aug 21 00:16:25 2014 +0100
+++ b/src/ex_cmds.h Tue Aug 12 10:31:37 2014 +0100
@@ -110,7 +110,7 @@
EX(CMD_args, "args", ex_args,
BANG|FILES|EDITCMD|ARGOPT|TRLBAR),
EX(CMD_argadd, "argadd", ex_argadd,
- BANG|NEEDARG|RANGE|NOTADR|ZEROR|FILES|TRLBAR),
+ BANG|RANGE|NOTADR|ZEROR|FILES|TRLBAR),
EX(CMD_argdelete, "argdelete", ex_argdelete,
BANG|RANGE|NOTADR|FILES|TRLBAR),
EX(CMD_argdo, "argdo", ex_listdo,
diff -r b9ec5ed29480 -r b95122e84f81 src/ex_cmds2.c
--- a/src/ex_cmds2.c Thu Aug 21 00:16:25 2014 +0100
+++ b/src/ex_cmds2.c Tue Aug 12 10:31:37 2014 +0100
@@ -1946,6 +1946,11 @@
#endif
/*
+ * Set default argument for ":argadd" command.
+ */
+ if (what == AL_ADD && STRLEN(str) == 0)
+ str = curbuf->b_fname;
+ /*
* Collect all file name arguments in "new_ga".
*/
if (get_arglist(&new_ga, str) == FAIL)
diff -r 35ec194cce5b -r 1333a7ca01af runtime/doc/editing.txt
--- a/runtime/doc/editing.txt Fri Aug 29 17:45:32 2014 +0200
+++ b/runtime/doc/editing.txt Sun Aug 24 18:55:01 2014 +0100
@@ -619,7 +619,8 @@
:argadd x a b x c
:0argadd x x a b c
:1argadd x a x b c
- :99argadd x a b c x
+ :$argadd x a b c x
+ :+2aradd y a b c x y
There is no check for duplicates, it is possible to
add a file to the argument list twice.
The currently edited file is not changed.
@@ -641,11 +642,19 @@
< {not in Vi} {not available when compiled without the
|+listcmds| feature}
-:{range}argd[elete] Delete the {range} files from the argument list.
+:[count]argd[elete]
+:[range]argd[elete] Delete the {range} files from the argument list.
When the last number in the range is too high, up to
the last argument is deleted. Example: >
- :10,1000argdel
-< Deletes arguments 10 and further, keeping 1-9.
+ :10,$argdel
+< Deletes arguments 10 and further, keeping 1-9. >
+ :$argd
+< Deletes just the last one. >
+ :argd
+ :.argd
+< Deletes the current argument. >
+ :%argd
+< Removes all the files from the arglist.
{not in Vi} {not available when compiled without the
|+listcmds| feature}
diff -r 35ec194cce5b -r 1333a7ca01af runtime/doc/windows.txt
--- a/runtime/doc/windows.txt Fri Aug 29 17:45:32 2014 +0200
+++ b/runtime/doc/windows.txt Sun Aug 24 18:55:01 2014 +0100
@@ -265,26 +265,40 @@
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.
- 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,
+:[count]q[uit] Quit current window if [count] is not given, otherwise close
+ window with window number equal to [count]. 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). 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 9 windows opened
+ :-quit " quit the previews window
+ :+quit " quit the next window
+ :+2quit " will also work as expected
+<
+:[count]q[uit]! Quit current window, unless [count] is given. For [count] see
+ |:quit| command. 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.
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).
- When there is only one window in the current tab page and
- there is another tab page, this closes the current tab page.
+:[count]clo[se][!]
+ Close current window if [count] is not given, otherwise close
+ window with window number equal to [count]. For [count] see
+ |:quit| command. 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). 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
@@ -298,14 +312,14 @@
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|
- 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.
+:[count]hid[e] Quit current window, unless it is the last window on the
+ screen. For [count] see |:quit| command. 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
'hidden' is restored after {cmd} has been executed.
@@ -316,15 +330,16 @@
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.
- 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
- given, then they become hidden. But modified buffers are
- never abandoned, so changes cannot get lost.
+:[count]on[ly][!]
+ Make the current window the only one on the screen. All other
+ windows are closed. For [count] see |:quit| command. 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 given, then they become hidden. But
+ modified buffers are never abandoned, so changes cannot get
+ lost.
==============================================================================
4. Moving cursor to other windows *window-move-cursor*
diff -r 35ec194cce5b -r 1333a7ca01af src/Makefile
--- a/src/Makefile Fri Aug 29 17:45:32 2014 +0200
+++ b/src/Makefile Sun Aug 24 18:55:01 2014 +0100
@@ -1907,7 +1907,8 @@
test70 test71 test72 test73 test74 test75 test76 test77 test78 test79 \
test80 test81 test82 test83 test84 test85 test86 test87 test88 test89 \
test90 test91 test92 test93 test94 test95 test96 test97 test98 test99 \
- test100 test101 test102 test103 test104 test105 test106 test107:
+ test100 test101 test102 test103 test104 test105 test106 test107 test108 \
+ test109:
cd testdir; rm [email protected]; $(MAKE) -f Makefile [email protected] VIMPROG=../$(VIMTARGET) $(GUI_TESTARG) SCRIPTSOURCE=../$(SCRIPTSOURCE)
testclean:
diff -r 35ec194cce5b -r 1333a7ca01af src/ex_cmds.h
--- a/src/ex_cmds.h Fri Aug 29 17:45:32 2014 +0200
+++ b/src/ex_cmds.h Sun Aug 24 18:55:01 2014 +0100
@@ -232,7 +232,7 @@
EX(CMD_clast, "clast", ex_cc,
RANGE|NOTADR|COUNT|TRLBAR|BANG),
EX(CMD_close, "close", ex_close,
- BANG|TRLBAR|CMDWIN),
+ BANG|RANGE|NOTADR|COUNT|TRLBAR|CMDWIN),
EX(CMD_cmap, "cmap", ex_map,
EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN),
EX(CMD_cmapclear, "cmapclear", ex_mapclear,
@@ -428,7 +428,7 @@
EX(CMD_highlight, "highlight", ex_highlight,
BANG|EXTRA|TRLBAR|SBOXOK|CMDWIN),
EX(CMD_hide, "hide", ex_hide,
- BANG|EXTRA|NOTRLCOM),
+ BANG|RANGE|NOTADR|COUNT|EXTRA|NOTRLCOM),
EX(CMD_history, "history", ex_history,
EXTRA|TRLBAR|CMDWIN),
EX(CMD_insert, "insert", ex_append,
@@ -676,7 +676,7 @@
EX(CMD_omenu, "omenu", ex_menu,
RANGE|NOTADR|ZEROR|EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN),
EX(CMD_only, "only", ex_only,
- BANG|TRLBAR),
+ BANG|NOTADR|RANGE|COUNT|TRLBAR),
EX(CMD_onoremap, "onoremap", ex_map,
EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN),
EX(CMD_onoremenu, "onoremenu", ex_menu,
@@ -756,7 +756,7 @@
EX(CMD_py3file, "py3file", ex_py3file,
RANGE|FILE1|NEEDARG|CMDWIN),
EX(CMD_quit, "quit", ex_quit,
- BANG|TRLBAR|CMDWIN),
+ BANG|RANGE|COUNT|NOTADR|TRLBAR|CMDWIN),
EX(CMD_quitall, "quitall", ex_quit_all,
BANG|TRLBAR),
EX(CMD_qall, "qall", ex_quit_all,
@@ -1206,3 +1206,13 @@
#define EXFLAG_PRINT 0x04 /* 'p': print */
#endif
+
+#define ADDRT_ABSOLUTE 0x001 /* number */
+#define ADDRT_CURPOS 0x002 /* '.' */
+#define ADDRT_LAST 0x004 /* '$' */
+#define ADDRT_MARK 0x010 /* "'" */
+#define ADDRT_SEARCH 0x020 /* '/' or '?' */
+#define ADDRT_REPEAT 0x040 /* "\?", "\/" or "\&" */
+#define ADDRT_LOCAL 0x100 /* '+[linenr], or -[linenr]' */
+#define ADDRT_ALL 0x200 /* '%' */
+#define ADDRT_VISUAL 0x400 /* '*' */
diff -r 35ec194cce5b -r 1333a7ca01af src/ex_docmd.c
--- a/src/ex_docmd.c Fri Aug 29 17:45:32 2014 +0200
+++ b/src/ex_docmd.c Sun Aug 24 18:55:01 2014 +0100
@@ -55,6 +55,7 @@
# define ex_delcommand ex_ni
#endif
+static int compute_count(addr_T *, linenr_T, linenr_T, linenr_T, int);
#ifdef FEAT_EVAL
static char_u *do_one_cmd __ARGS((char_u **, int, struct condstack *, char_u *(*fgetline)(int, void *, int), void *cookie));
#else
@@ -128,7 +129,7 @@
#endif
static int check_more __ARGS((int, int));
-static linenr_T get_address __ARGS((char_u **, int skip, int to_other_file));
+static addr_T get_address __ARGS((char_u **, int skip, int to_other_file));
static void get_flags __ARGS((exarg_T *eap));
#if !defined(FEAT_PERL) \
|| !defined(FEAT_PYTHON) || !defined(FEAT_PYTHON3) \
@@ -1675,6 +1676,45 @@
}
#endif
+ static int
+compute_count(addr, first, current, last, addr_all)
+ addr_T *addr;
+ linenr_T first;
+ linenr_T current;
+ linenr_T last;
+ int addr_all;
+{
+ if (addr->type & ADDRT_MARK ||
+ addr->type & ADDRT_SEARCH ||
+ addr->type & ADDRT_REPEAT ||
+ addr->type & ADDRT_VISUAL ||
+ addr->type & ADDRT_ALL && !addr_all)
+ {
+ return 0;
+ }
+ else if (addr->type & ADDRT_ALL && addr_all)
+ {
+ addr->lnum = (last > 0) ? last : 1;
+ return 2;
+ }
+ else if (addr->type & ADDRT_LAST)
+ addr->lnum = last;
+ else if (!(addr->type & ADDRT_ABSOLUTE)) {
+ addr->lnum = current;
+ }
+ if (addr->type & ADDRT_LOCAL)
+ {
+ addr->lnum += addr->local;
+ /* avoid E16 if address is negative */
+ if (addr->lnum < first)
+ addr->lnum = first;
+ if (addr->lnum > last)
+ addr->lnum = last;
+ }
+ return 1;
+}
+
+
/*
* Execute one Ex command.
*
@@ -1712,6 +1752,7 @@
void *cookie; /* argument for fgetline() */
{
char_u *p;
+ addr_T addr1, addr2;
linenr_T lnum;
long n;
char_u *errormsg = NULL; /* error message */
@@ -1725,6 +1766,9 @@
#endif
cmdmod_T save_cmdmod;
int ni; /* set when Not Implemented */
+ win_T *wp;
+ buf_T *buf;
+ char_u c;
vim_memset(&ea, 0, sizeof(ea));
ea.line1 = 1;
@@ -2020,10 +2064,11 @@
ea.line1 = ea.line2;
ea.line2 = curwin->w_cursor.lnum; /* default is current line number */
ea.cmd = skipwhite(ea.cmd);
- lnum = get_address(&ea.cmd, ea.skip, ea.addr_count == 0);
+ addr1 = addr2;
+ addr2 = get_address(&ea.cmd, ea.skip, ea.addr_count == 0);
if (ea.cmd == NULL) /* error detected */
goto doend;
- if (lnum == MAXLNUM)
+ if (addr2.lnum == MAXLNUM)
{
if (*ea.cmd == '%') /* '%' - all lines */
{
@@ -2031,6 +2076,7 @@
ea.line1 = 1;
ea.line2 = curbuf->b_ml.ml_line_count;
++ea.addr_count;
+ addr2.type |= ADDRT_ALL;
}
/* '*' - visual area */
else if (*ea.cmd == '*' && vim_strchr(p_cpo, CPO_STAR) == NULL)
@@ -2053,7 +2099,7 @@
}
}
else
- ea.line2 = lnum;
+ ea.line2 = addr2.lnum;
ea.addr_count++;
if (*ea.cmd == ';')
@@ -2069,9 +2115,10 @@
/* One address given: set start and end lines */
if (ea.addr_count == 1)
{
+ addr1 = addr2;
ea.line1 = ea.line2;
/* ... but only implicit: really no address given */
- if (lnum == MAXLNUM)
+ if (addr2.lnum == MAXLNUM)
ea.addr_count = 0;
}
@@ -2190,6 +2237,227 @@
goto doend;
}
+ /*
+ * For some commands addr might be used not as a line number
+ */
+ switch(ea.cmdidx)
+ {
+ case CMD_close:
+ case CMD_hide:
+ case CMD_only:
+ case CMD_quit:
+ if (ea.addr_count == 0)
+ break;
+ if ( addr2.type & ADDRT_MARK ||
+ addr2.type & ADDRT_SEARCH ||
+ addr2.type & ADDRT_REPEAT ||
+ addr2.type & ADDRT_ALL ||
+ addr2.type & ADDRT_VISUAL)
+ {
+ /* emit E16 */
+ errormsg = (char_u *)_(e_invrange);
+ goto doend;
+ }
+ if (addr2.type & ADDRT_LAST)
+ {
+ lnum = 0;
+ for (wp = firstwin; wp != NULL; wp = wp->w_next)
+ lnum++;
+ if (addr2.type & ADDRT_LOCAL)
+ {
+ lnum += addr2.local;
+ /* avoid E16 if address is negative */
+ if (lnum <= 0)
+ lnum = 1;
+ }
+ ea.line1 = ea.line2 = addr2.lnum = lnum;
+ }
+ else if ((addr2.type & ADDRT_LOCAL || addr2.type & ADDRT_CURPOS) &&
+ !(addr2.type & ADDRT_ABSOLUTE))
+ {
+ lnum = 0;
+ for (wp = firstwin; wp != NULL; wp = wp->w_next)
+ {
+ lnum++;
+ if (wp == curwin)
+ break;
+ }
+ if (addr2.type & ADDRT_LOCAL)
+ {
+ lnum = lnum + addr2.local;
+ /* avoid E16 if address is negative */
+ if (lnum <= 0)
+ lnum = 1;
+ }
+ ea.line1 = ea.line2 = addr2.lnum = lnum;
+ }
+ break;
+ case CMD_argument:
+ case CMD_sargument:
+ case CMD_argadd:
+ case CMD_argedit:
+ if (ea.addr_count == 0)
+ break;
+ if (compute_count(&addr2, 0,
+ curwin->w_arg_idx + 1, ARGCOUNT, FALSE) == 0)
+ {
+ /* emit E16 */
+ errormsg = (char_u *)_(e_invrange);
+ goto doend;
+ }
+ else
+ {
+ ea.line1 = ea.line2 = addr2.lnum;
+ }
+ break;
+ case CMD_argdelete:
+ if (ea.addr_count > 1) {
+ if (compute_count(&addr1, 1,
+ curwin->w_arg_idx + 1, ARGCOUNT, FALSE) == 0)
+ {
+ /* emit E16 */
+ errormsg = (char_u *)_(e_invrange);
+ goto doend;
+ }
+ else
+ ea.line1 = addr1.lnum;
+ }
+
+ c = skipwhite(p)[0];
+ if (ea.addr_count > 0)
+ {
+ switch (compute_count(&addr2, 1,
+ curwin->w_arg_idx + 1, ARGCOUNT, TRUE))
+ {
+ case 2:
+ ea.line1 = 1;
+ default:
+ case 1:
+ ea.line2 = addr2.lnum;
+ break;
+ case 0:
+ /* emit E16 */
+ errormsg = (char_u *)_(e_invrange);
+ goto doend;
+ break;
+ };
+ }
+ else if (c == '\0' || c == '|') /* expand :argdelete to :.argdelete */
+ {
+ ea.line2 = addr2.lnum = curwin->w_arg_idx + 1;
+ ea.addr_count = 1;
+ }
+
+ if (ea.addr_count <= 1) /* expand :Nargdelete to :N,Nargdelete */
+ {
+ addr1 = addr2;
+ ea.line1 = ea.line2;
+ }
+ break;
+ case CMD_bunload:
+ case CMD_bdelete:
+ case CMD_bwipeout:
+ if (ea.addr_count > 1) {
+ n = addr1.type;
+ addr1.type &= ~ADDRT_LOCAL;
+ if (compute_count(&addr1, firstbuf->b_fnum,
+ curbuf->b_fnum, lastbuf->b_fnum, FALSE) == 0)
+ {
+ /* emit E16 */
+ errormsg = (char_u *)_(e_invrange);
+ goto doend;
+ }
+ else if (n & ADDRT_LOCAL)
+ {
+ buf = firstbuf;
+ while (buf->b_next != NULL
+ && buf->b_fnum < addr1.lnum)
+ buf = buf->b_next;
+ while (addr1.local != 0)
+ {
+ if (addr1.local < 0)
+ {
+ addr1.local += 1;
+ if (buf->b_prev == NULL)
+ break;
+ buf = buf->b_prev;
+ if (ea.cmdidx != CMD_bwipeout)
+ /* skip over unloaded buffers */
+ while (buf->b_prev != NULL && buf->b_ml.ml_mfp == NULL)
+ buf = buf->b_prev;
+ }
+ else
+ {
+ addr1.local -= 1;
+ if (buf->b_next == NULL)
+ break;
+ buf = buf->b_next;
+ if (ea.cmdidx != CMD_bwipeout)
+ /* skip over unloaded buffers */
+ while (buf->b_next != NULL && buf->b_ml.ml_mfp == NULL)
+ buf = buf->b_next;
+ }
+ }
+ addr1.lnum = buf->b_fnum;
+ }
+ ea.line1 = addr1.lnum;
+ }
+
+ if (ea.addr_count > 0) {
+ n = addr2.type;
+ addr2.type &= ~ADDRT_LOCAL;
+ switch (compute_count(&addr2, firstbuf->b_fnum,
+ curbuf->b_fnum, lastbuf->b_fnum, TRUE))
+ {
+ case 2:
+ ea.line1 = firstbuf->b_fnum;
+ default:
+ case 1:
+ if (n && ADDRT_LOCAL)
+ {
+ buf = firstbuf;
+ while (buf->b_next != NULL
+ && buf->b_fnum < addr2.lnum)
+ buf = buf->b_next;
+ while (addr2.local != 0)
+ {
+ if (addr2.local < 0)
+ {
+ addr2.local += 1;
+ if (buf->b_prev == NULL)
+ break;
+ buf = buf->b_prev;
+ if (ea.cmdidx != CMD_bwipeout)
+ /* skip over unloaded buffers */
+ while (buf->b_prev != NULL && buf->b_ml.ml_mfp == NULL)
+ buf = buf->b_prev;
+ }
+ else
+ {
+ addr2.local -= 1;
+ if (buf->b_next == NULL)
+ break;
+ buf = buf->b_next;
+ if (ea.cmdidx != CMD_bwipeout)
+ /* skip over unloaded buffers */
+ while (buf->b_next != NULL && buf->b_ml.ml_mfp == NULL)
+ buf = buf->b_next;
+ }
+ }
+ addr2.lnum = buf->b_fnum;
+ }
+ ea.line2 = addr2.lnum;
+ break;
+ case 0:
+ /* emit E16 */
+ errormsg = (char_u *)_(e_invrange);
+ goto doend;
+ break;
+ };
+ }
+ break;
+ }
+
ni = (
#ifdef FEAT_USR_CMDS
!USER_CMDIDX(ea.cmdidx) &&
@@ -3358,7 +3626,7 @@
++p;
}
-/*
+/*.
* 5. parse arguments
*/
#ifdef FEAT_USR_CMDS
@@ -4102,7 +4370,7 @@
*
* Return MAXLNUM when no Ex address was found.
*/
- static linenr_T
+ static addr_T
get_address(ptr, skip, to_other_file)
char_u **ptr;
int skip; /* only skip the address, don't use it */
@@ -4114,22 +4382,26 @@
char_u *cmd;
pos_T pos;
pos_T *fp;
- linenr_T lnum;
+ addr_T addr;
cmd = skipwhite(*ptr);
- lnum = MAXLNUM;
+ addr.lnum = MAXLNUM;
+ addr.local = 0;
+ addr.type = 0;
do
{
switch (*cmd)
{
case '.': /* '.' - Cursor position */
++cmd;
- lnum = curwin->w_cursor.lnum;
+ addr.lnum = curwin->w_cursor.lnum;
+ addr.type = ADDRT_CURPOS;
break;
case '$': /* '$' - last line */
++cmd;
- lnum = curbuf->b_ml.ml_line_count;
+ addr.lnum = curbuf->b_ml.ml_line_count;
+ addr.type = ADDRT_LAST;
break;
case '\'': /* ''' - mark */
@@ -4146,9 +4418,10 @@
* used by itself: ":'M". */
fp = getmark(*cmd, to_other_file && cmd[1] == NUL);
++cmd;
+ addr.type = ADDRT_MARK;
if (fp == (pos_T *)-1)
/* Jumped to another file. */
- lnum = curwin->w_cursor.lnum;
+ addr.lnum = curwin->w_cursor.lnum;
else
{
if (check_mark(fp) == FAIL)
@@ -4156,7 +4429,7 @@
cmd = NULL;
goto error;
}
- lnum = fp->lnum;
+ addr.lnum = fp->lnum;
}
}
break;
@@ -4177,8 +4450,8 @@
* When '/' or '?' follows another address, start
* from there.
*/
- if (lnum != MAXLNUM)
- curwin->w_cursor.lnum = lnum;
+ if (addr.lnum != MAXLNUM)
+ curwin->w_cursor.lnum = addr.lnum;
/*
* Start a forward search at the end of the line.
* Start a backward search at the start of the line.
@@ -4198,7 +4471,8 @@
cmd = NULL;
goto error;
}
- lnum = curwin->w_cursor.lnum;
+ addr.lnum = curwin->w_cursor.lnum;
+ addr.type = ADDRT_SEARCH;
curwin->w_cursor = pos;
/* adjust command string pointer */
cmd += searchcmdlen;
@@ -4224,8 +4498,9 @@
* When search follows another address, start from
* there.
*/
- if (lnum != MAXLNUM)
- pos.lnum = lnum;
+ addr.type = ADDRT_REPEAT;
+ if (addr.lnum != MAXLNUM)
+ pos.lnum = addr.lnum;
else
pos.lnum = curwin->w_cursor.lnum;
@@ -4241,7 +4516,7 @@
*cmd == '?' ? BACKWARD : FORWARD,
(char_u *)"", 1L, SEARCH_MSG,
i, (linenr_T)0, NULL) != FAIL)
- lnum = pos.lnum;
+ addr.lnum = pos.lnum;
else
{
cmd = NULL;
@@ -4253,7 +4528,10 @@
default:
if (VIM_ISDIGIT(*cmd)) /* absolute line number */
- lnum = getdigits(&cmd);
+ {
+ addr.lnum = getdigits(&cmd);
+ addr.type = ADDRT_ABSOLUTE;
+ }
}
for (;;)
@@ -4262,8 +4540,9 @@
if (*cmd != '-' && *cmd != '+' && !VIM_ISDIGIT(*cmd))
break;
- if (lnum == MAXLNUM)
- lnum = curwin->w_cursor.lnum; /* "+1" is same as ".+1" */
+ addr.type |= ADDRT_LOCAL;
+ if (addr.lnum == MAXLNUM)
+ addr.lnum = curwin->w_cursor.lnum; /* "+1" is same as ".+1" */
if (VIM_ISDIGIT(*cmd))
i = '+'; /* "number" is same as "+number" */
else
@@ -4273,15 +4552,21 @@
else
n = getdigits(&cmd);
if (i == '-')
- lnum -= n;
+ {
+ addr.lnum -= n;
+ addr.local -= n;
+ }
else
- lnum += n;
+ {
+ addr.lnum += n;
+ addr.local += n;
+ }
}
} while (*cmd == '/' || *cmd == '?');
error:
*ptr = cmd;
- return lnum;
+ return addr;
}
/*
@@ -6565,6 +6850,11 @@
ex_quit(eap)
exarg_T *eap;
{
+ win_T *wp;
+ win_T *cwp;
+ buf_T *buf;
+ int wnr;
+
#ifdef FEAT_CMDWIN
if (cmdwin_type != 0)
{
@@ -6578,11 +6868,28 @@
text_locked_msg();
return;
}
+ 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;
+ }
#ifdef FEAT_AUTOCMD
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 && buf->b_closing))
return;
#endif
@@ -6615,7 +6922,7 @@
need_mouse_correct = TRUE;
# endif
/* 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);
#endif
}
}
@@ -6677,6 +6984,8 @@
ex_close(eap)
exarg_T *eap;
{
+ win_T *win;
+ int winnr = 0;
# ifdef FEAT_CMDWIN
if (cmdwin_type != 0)
cmdwin_result = Ctrl_C;
@@ -6687,7 +6996,21 @@
&& !curbuf_locked()
#endif
)
- ex_win_close(eap->forceit, curwin, NULL);
+ {
+ 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);
+ }
+ }
}
# ifdef FEAT_QUICKFIX
@@ -6891,9 +7214,23 @@
ex_only(eap)
exarg_T *eap;
{
+ win_T *wp;
+ int wnr;
# ifdef FEAT_GUI
need_mouse_correct = TRUE;
# endif
+ 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);
}
@@ -6915,6 +7252,9 @@
ex_hide(eap)
exarg_T *eap;
{
+ win_T *win;
+ int winnr = 0;
+
if (*eap->arg != NUL && check_nextcmd(eap->arg) == NULL)
eap->errmsg = e_invarg;
else
@@ -6927,7 +7267,19 @@
# ifdef FEAT_GUI
need_mouse_correct = TRUE;
# endif
- 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);
+ }
}
#endif
}
@@ -8659,9 +9011,9 @@
ex_copymove(eap)
exarg_T *eap;
{
- long n;
-
- n = get_address(&eap->arg, FALSE, FALSE);
+ addr_T addr;
+
+ addr = get_address(&eap->arg, FALSE, FALSE);
if (eap->arg == NULL) /* error detected */
{
eap->nextcmd = NULL;
@@ -8670,9 +9022,10 @@
get_flags(eap);
/*
- * move or copy lines from 'eap->line1'-'eap->line2' to below line 'n'
+ * move or copy lines from 'eap->line1'-'eap->line2' to below line
+ * 'addr.lnum'
*/
- if (n == MAXLNUM || n < 0 || n > curbuf->b_ml.ml_line_count)
+ if (addr.lnum == MAXLNUM || addr.lnum < 0 || addr.lnum > curbuf->b_ml.ml_line_count)
{
EMSG(_(e_invaddr));
return;
@@ -8680,11 +9033,11 @@
if (eap->cmdidx == CMD_move)
{
- if (do_move(eap->line1, eap->line2, n) == FAIL)
+ if (do_move(eap->line1, eap->line2, addr.lnum) == FAIL)
return;
}
else
- ex_copy(eap->line1, eap->line2, n);
+ ex_copy(eap->line1, eap->line2, addr.lnum);
u_clearline();
beginline(BL_SOL | BL_FIX);
ex_may_print(eap);
diff -r 35ec194cce5b -r 1333a7ca01af src/structs.h
--- a/src/structs.h Fri Aug 29 17:45:32 2014 +0200
+++ b/src/structs.h Sun Aug 24 18:55:01 2014 +0100
@@ -21,6 +21,16 @@
#endif
/*
+ *
+ */
+typedef struct
+{
+ linenr_T lnum; /* addr */
+ linenr_T local; /* addr from + and - modifiers */
+ int type; /* */
+} addr_T;
+
+/*
* position in file or buffer
*/
typedef struct
diff -r 35ec194cce5b -r 1333a7ca01af src/testdir/test108.in
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/testdir/test108.in Sun Aug 24 18:55:01 2014 +0100
@@ -0,0 +1,153 @@
+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
+:3wincmd 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
+: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
+
+
diff -r 35ec194cce5b -r 1333a7ca01af src/testdir/test108.ok
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/testdir/test108.ok Sun Aug 24 18:55:01 2014 +0100
@@ -0,0 +1,22 @@
+6 5 4 2 1
+5 4 2 1
+5 4 2
+5 2
+7 5 2
+7 5
+
+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
diff -r 35ec194cce5b -r 1333a7ca01af src/testdir/test109.in
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/testdir/test109.in Sun Aug 24 18:55:01 2014 +0100
@@ -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
+
+
diff -r 35ec194cce5b -r 1333a7ca01af src/testdir/test109.ok
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/testdir/test109.ok Sun Aug 24 18:55:01 2014 +0100
@@ -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
diff -r 35ec194cce5b -r 1333a7ca01af src/window.c
--- a/src/window.c Fri Aug 29 17:45:32 2014 +0200
+++ b/src/window.c Sun Aug 24 18:55:01 2014 +0100
@@ -199,14 +199,22 @@
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 + 5, sizeof(cbuf) - 5,
+ "%ld", Prenum);
+ do_cmdline_cmd(cbuf);
break;
#if defined(FEAT_WINDOWS) && defined(FEAT_QUICKFIX)
@@ -235,7 +243,11 @@
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 */
signature.asc
Description: Digital signature
