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 */

Attachment: signature.asc
Description: Digital signature

Raspunde prin e-mail lui