]> granicus.if.org Git - vim/commitdiff
patch 8.0.0259: tab commands do not handle count correctly v8.0.0259
authorBram Moolenaar <Bram@vim.org>
Sun, 29 Jan 2017 13:48:10 +0000 (14:48 +0100)
committerBram Moolenaar <Bram@vim.org>
Sun, 29 Jan 2017 13:48:10 +0000 (14:48 +0100)
Problem:    Tab commands do not handle count correctly. (Ken Hamada)
Solution:   Add ADDR_TABS_RELATIVE. (Hirohito Higashi)

src/ex_cmds.h
src/ex_docmd.c
src/testdir/test_tabpage.vim
src/version.c

index d70ff6a7b709240ab1a9e1bade21f17cbc87fdaf..88dfbb987482fa028439434c17b113cd41d94498 100644 (file)
@@ -65,7 +65,8 @@
 #define ADDR_LOADED_BUFFERS    3
 #define ADDR_BUFFERS           4
 #define ADDR_TABS              5
-#define ADDR_QUICKFIX          6
+#define ADDR_TABS_RELATIVE     6   /* Tab page that only relative */
+#define ADDR_QUICKFIX          7
 #define ADDR_OTHER             99
 
 #ifndef DO_DECLARE_EXCMD
@@ -1425,9 +1426,9 @@ EX(CMD_tags,              "tags",         do_tags,
                        ADDR_LINES),
 EX(CMD_tab,            "tab",          ex_wrongmodifier,
                        NEEDARG|EXTRA|NOTRLCOM,
-                       ADDR_LINES),
+                       ADDR_TABS),
 EX(CMD_tabclose,       "tabclose",     ex_tabclose,
-                       RANGE|NOTADR|COUNT|BANG|TRLBAR|CMDWIN,
+                       BANG|RANGE|NOTADR|ZEROR|EXTRA|NOSPC|TRLBAR|CMDWIN,
                        ADDR_TABS),
 EX(CMD_tabdo,          "tabdo",        ex_listdo,
                        NEEDARG|EXTRA|NOTRLCOM|RANGE|NOTADR|DFLALL,
@@ -1440,34 +1441,34 @@ EX(CMD_tabfind,         "tabfind",      ex_splitview,
                        ADDR_TABS),
 EX(CMD_tabfirst,       "tabfirst",     ex_tabnext,
                        TRLBAR,
-                       ADDR_LINES),
+                       ADDR_TABS),
 EX(CMD_tabmove,                "tabmove",      ex_tabmove,
                        RANGE|NOTADR|ZEROR|EXTRA|NOSPC|TRLBAR,
                        ADDR_TABS),
 EX(CMD_tablast,                "tablast",      ex_tabnext,
                        TRLBAR,
-                       ADDR_LINES),
+                       ADDR_TABS),
 EX(CMD_tabnext,                "tabnext",      ex_tabnext,
-                       RANGE|NOTADR|COUNT|TRLBAR,
-                       ADDR_LINES),
+                       RANGE|NOTADR|ZEROR|EXTRA|NOSPC|TRLBAR,
+                       ADDR_TABS),
 EX(CMD_tabnew,         "tabnew",       ex_splitview,
                        BANG|FILE1|RANGE|NOTADR|ZEROR|EDITCMD|ARGOPT|TRLBAR,
                        ADDR_TABS),
 EX(CMD_tabonly,                "tabonly",      ex_tabonly,
-                       BANG|RANGE|NOTADR|TRLBAR|CMDWIN,
+                       BANG|RANGE|NOTADR|ZEROR|EXTRA|NOSPC|TRLBAR|CMDWIN,
                        ADDR_TABS),
 EX(CMD_tabprevious,    "tabprevious",  ex_tabnext,
-                       RANGE|NOTADR|COUNT|TRLBAR,
-                       ADDR_LINES),
+                       RANGE|NOTADR|ZEROR|EXTRA|NOSPC|TRLBAR,
+                       ADDR_TABS_RELATIVE),
 EX(CMD_tabNext,                "tabNext",      ex_tabnext,
-                       RANGE|NOTADR|COUNT|TRLBAR,
-                       ADDR_LINES),
+                       RANGE|NOTADR|ZEROR|EXTRA|NOSPC|TRLBAR,
+                       ADDR_TABS_RELATIVE),
 EX(CMD_tabrewind,      "tabrewind",    ex_tabnext,
                        TRLBAR,
-                       ADDR_LINES),
+                       ADDR_TABS),
 EX(CMD_tabs,           "tabs",         ex_tabs,
                        TRLBAR|CMDWIN,
-                       ADDR_LINES),
+                       ADDR_TABS),
 EX(CMD_tcl,            "tcl",          ex_tcl,
                        RANGE|EXTRA|NEEDARG|CMDWIN,
                        ADDR_LINES),
index 192f45d194b838d506f1c7b88270760e5d3fd15c..90a009d935325fdd0c4fd01302226e84262577a4 100644 (file)
@@ -2162,8 +2162,7 @@ do_one_cmd(
                ea.line2 = curwin->w_cursor.lnum;
                break;
            case ADDR_WINDOWS:
-               lnum = CURRENT_WIN_NR;
-               ea.line2 = lnum;
+               ea.line2 = CURRENT_WIN_NR;
                break;
            case ADDR_ARGUMENTS:
                ea.line2 = curwin->w_arg_idx + 1;
@@ -2175,8 +2174,10 @@ do_one_cmd(
                ea.line2 = curbuf->b_fnum;
                break;
            case ADDR_TABS:
-               lnum = CURRENT_TAB_NR;
-               ea.line2 = lnum;
+               ea.line2 = CURRENT_TAB_NR;
+               break;
+           case ADDR_TABS_RELATIVE:
+               ea.line2 = 1;
                break;
 #ifdef FEAT_QUICKFIX
            case ADDR_QUICKFIX:
@@ -2235,6 +2236,10 @@ do_one_cmd(
                            goto doend;
                        }
                        break;
+                   case ADDR_TABS_RELATIVE:
+                       errormsg = (char_u *)_(e_invrange);
+                       goto doend;
+                       break;
                    case ADDR_ARGUMENTS:
                        if (ARGCOUNT == 0)
                            ea.line1 = ea.line2 = 0;
@@ -2710,6 +2715,9 @@ do_one_cmd(
            case ADDR_TABS:
                ea.line2 = LAST_TAB_NR;
                break;
+           case ADDR_TABS_RELATIVE:
+               ea.line2 = 1;
+               break;
            case ADDR_ARGUMENTS:
                if (ARGCOUNT == 0)
                    ea.line1 = ea.line2 = 0;
@@ -2786,7 +2794,8 @@ do_one_cmd(
            /*
             * Be vi compatible: no error message for out of range.
             */
-           if (ea.line2 > curbuf->b_ml.ml_line_count)
+           if (ea.addr_type == ADDR_LINES
+                   && ea.line2 > curbuf->b_ml.ml_line_count)
                ea.line2 = curbuf->b_ml.ml_line_count;
        }
     }
@@ -4427,6 +4436,11 @@ get_address(
                    case ADDR_TABS:
                        lnum = CURRENT_TAB_NR;
                        break;
+                   case ADDR_TABS_RELATIVE:
+                       EMSG(_(e_invrange));
+                       cmd = NULL;
+                       goto error;
+                       break;
 #ifdef FEAT_QUICKFIX
                    case ADDR_QUICKFIX:
                        lnum = qf_get_cur_valid_idx(eap);
@@ -4464,6 +4478,11 @@ get_address(
                    case ADDR_TABS:
                        lnum = LAST_TAB_NR;
                        break;
+                   case ADDR_TABS_RELATIVE:
+                       EMSG(_(e_invrange));
+                       cmd = NULL;
+                       goto error;
+                       break;
 #ifdef FEAT_QUICKFIX
                    case ADDR_QUICKFIX:
                        lnum = qf_get_size(eap);
@@ -4646,6 +4665,9 @@ get_address(
                    case ADDR_TABS:
                        lnum = CURRENT_TAB_NR;
                        break;
+                   case ADDR_TABS_RELATIVE:
+                       lnum = 1;
+                       break;
 #ifdef FEAT_QUICKFIX
                    case ADDR_QUICKFIX:
                        lnum = qf_get_cur_valid_idx(eap);
@@ -4662,7 +4684,14 @@ get_address(
                n = 1;
            else
                n = getdigits(&cmd);
-           if (addr_type == ADDR_LOADED_BUFFERS
+
+           if (addr_type == ADDR_TABS_RELATIVE)
+           {
+               EMSG(_(e_invrange));
+               cmd = NULL;
+               goto error;
+           }
+           else if (addr_type == ADDR_LOADED_BUFFERS
                    || addr_type == ADDR_BUFFERS)
                lnum = compute_buffer_local_count(
                                    addr_type, lnum, (i == '-') ? -1 * n : n);
@@ -4795,6 +4824,9 @@ invalid_range(exarg_T *eap)
                if (eap->line2 > LAST_TAB_NR)
                    return (char_u *)_(e_invrange);
                break;
+           case ADDR_TABS_RELATIVE:
+               /* Do nothing */
+               break;
 #ifdef FEAT_QUICKFIX
            case ADDR_QUICKFIX:
                if (eap->line2 != 1 && eap->line2 > qf_get_size(eap))
@@ -5452,6 +5484,104 @@ getargopt(exarg_T *eap)
     return OK;
 }
 
+/*
+ * Handle the argument for a tabpage related ex command.
+ * Returns a tabpage number.
+ * When an error is encountered then eap->errmsg is set.
+ */
+    static int
+get_tabpage_arg(exarg_T *eap)
+{
+    int tab_number;
+    int unaccept_arg0 = (eap->cmdidx == CMD_tabmove) ? 0 : 1;
+
+    if (eap->arg && *eap->arg != NUL)
+    {
+       char_u *p = eap->arg;
+       char_u *p_save;
+       int    relative = 0; /* argument +N/-N means: go to N places to the
+                             * right/left relative to the current position. */
+
+       if (*p == '-')
+       {
+           relative = -1;
+           p++;
+       }
+       else if (*p == '+')
+       {
+           relative = 1;
+           p++;
+       }
+
+       p_save = p;
+       tab_number = getdigits(&p);
+
+       if (relative == 0)
+       {
+           if (STRCMP(p, "$") == 0)
+               tab_number = LAST_TAB_NR;
+           else if (p == p_save || *p_save == '-' || *p != NUL
+                   || tab_number > LAST_TAB_NR)
+           {
+               /* No numbers as argument. */
+               eap->errmsg = e_invarg;
+               goto theend;
+           }
+       }
+       else
+       {
+           if (*p_save == NUL)
+               tab_number = 1;
+           else if (p == p_save || *p_save == '-' || *p != NUL
+                   || tab_number == 0)
+           {
+               /* No numbers as argument. */
+               eap->errmsg = e_invarg;
+               goto theend;
+           }
+           tab_number = tab_number * relative + tabpage_index(curtab);
+           if (!unaccept_arg0 && relative == -1)
+               --tab_number;
+       }
+       if (tab_number < unaccept_arg0 || tab_number > LAST_TAB_NR)
+           eap->errmsg = e_invarg;
+    }
+    else if (eap->addr_count > 0)
+    {
+       if (unaccept_arg0 && eap->line2 == 0)
+           eap->errmsg = e_invrange;
+       else
+       {
+           tab_number = eap->line2;
+           if (!unaccept_arg0 && **eap->cmdlinep == '-')
+           {
+               --tab_number;
+               if (tab_number < unaccept_arg0)
+                   eap->errmsg = e_invarg;
+           }
+       }
+    }
+    else
+    {
+       switch (eap->cmdidx)
+       {
+       case CMD_tabnext:
+           tab_number = tabpage_index(curtab) + 1;
+           if (tab_number > LAST_TAB_NR)
+               tab_number = 1;
+           break;
+       case CMD_tabmove:
+           tab_number = LAST_TAB_NR;
+           break;
+       default:
+           tab_number = tabpage_index(curtab);
+       }
+    }
+
+theend:
+    return tab_number;
+}
+
 /*
  * ":abbreviate" and friends.
  */
@@ -7444,6 +7574,7 @@ ex_win_close(
 ex_tabclose(exarg_T *eap)
 {
     tabpage_T  *tp;
+    int                tab_number;
 
 # ifdef FEAT_CMDWIN
     if (cmdwin_type != 0)
@@ -7454,9 +7585,10 @@ ex_tabclose(exarg_T *eap)
            EMSG(_("E784: Cannot close last tab page"));
        else
        {
-           if (eap->addr_count > 0)
+           tab_number = get_tabpage_arg(eap);
+           if (eap->errmsg == NULL)
            {
-               tp = find_tabpage((int)eap->line2);
+               tp = find_tabpage(tab_number);
                if (tp == NULL)
                {
                    beep_flush();
@@ -7467,13 +7599,13 @@ ex_tabclose(exarg_T *eap)
                    tabpage_close_other(tp, eap->forceit);
                    return;
                }
-           }
-           if (!text_locked()
+               else if (!text_locked()
 #ifdef FEAT_AUTOCMD
-                   && !curbuf_locked()
+                       && !curbuf_locked()
 #endif
-              )
-               tabpage_close(eap->forceit);
+               )
+                   tabpage_close(eap->forceit);
+           }
        }
 }
 
@@ -7485,6 +7617,7 @@ ex_tabonly(exarg_T *eap)
 {
     tabpage_T  *tp;
     int                done;
+    int                tab_number;
 
 # ifdef FEAT_CMDWIN
     if (cmdwin_type != 0)
@@ -7495,24 +7628,27 @@ ex_tabonly(exarg_T *eap)
            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 (done = 0; done < 1000; ++done)
+           tab_number = get_tabpage_arg(eap);
+           if (eap->errmsg == NULL)
            {
-               FOR_ALL_TABPAGES(tp)
-                   if (tp->tp_topframe != topframe)
-                   {
-                       tabpage_close_other(tp, eap->forceit);
-                       /* if we failed to close it quit */
-                       if (valid_tabpage(tp))
-                           done = 1000;
-                       /* start over, "tp" is now invalid */
+               goto_tabpage(tab_number);
+               /* Repeat this up to a 1000 times, because autocommands may
+                * mess up the lists. */
+               for (done = 0; done < 1000; ++done)
+               {
+                   FOR_ALL_TABPAGES(tp)
+                       if (tp->tp_topframe != topframe)
+                       {
+                           tabpage_close_other(tp, eap->forceit);
+                           /* if we failed to close it quit */
+                           if (valid_tabpage(tp))
+                               done = 1000;
+                           /* start over, "tp" is now invalid */
+                           break;
+                       }
+                   if (first_tabpage->tp_next == NULL)
                        break;
-                   }
-               if (first_tabpage->tp_next == NULL)
-                   break;
+               }
            }
        }
 }
@@ -8254,6 +8390,8 @@ tabpage_new(void)
     static void
 ex_tabnext(exarg_T *eap)
 {
+    int tab_number;
+
     switch (eap->cmdidx)
     {
        case CMD_tabfirst:
@@ -8265,10 +8403,40 @@ ex_tabnext(exarg_T *eap)
            break;
        case CMD_tabprevious:
        case CMD_tabNext:
-           goto_tabpage(eap->addr_count == 0 ? -1 : -(int)eap->line2);
+           if (eap->arg && *eap->arg != NUL)
+           {
+               char_u *p = eap->arg;
+               char_u *p_save = p;
+
+               tab_number = getdigits(&p);
+               if (p == p_save || *p_save == '-' || *p != NUL
+                           || tab_number == 0)
+               {
+                   /* No numbers as argument. */
+                   eap->errmsg = e_invarg;
+                   return;
+               }
+           }
+           else
+           {
+               if (eap->addr_count == 0)
+                   tab_number = 1;
+               else
+               {
+                   tab_number = eap->line2;
+                   if (tab_number < 1)
+                   {
+                       eap->errmsg = e_invrange;
+                       return;
+                   }
+               }
+           }
+           goto_tabpage(-tab_number);
            break;
        default: /* CMD_tabnext */
-           goto_tabpage(eap->addr_count == 0 ? 0 : (int)eap->line2);
+           tab_number = get_tabpage_arg(eap);
+           if (eap->errmsg == NULL)
+               goto_tabpage(tab_number);
            break;
     }
 }
@@ -8281,59 +8449,9 @@ ex_tabmove(exarg_T *eap)
 {
     int tab_number;
 
-    if (eap->arg && *eap->arg != NUL)
-    {
-       char_u *p = eap->arg;
-       int    relative = 0; /* argument +N/-N means: move N places to the
-                             * right/left relative to the current position. */
-
-       if (*eap->arg == '-')
-       {
-           relative = -1;
-           p = eap->arg + 1;
-       }
-       else if (*eap->arg == '+')
-       {
-           relative = 1;
-           p = eap->arg + 1;
-       }
-       else
-           p = eap->arg;
-
-       if (relative == 0)
-       {
-           if (STRCMP(p, "$") == 0)
-               tab_number = LAST_TAB_NR;
-           else if (p == skipdigits(p))
-           {
-               /* No numbers as argument. */
-               eap->errmsg = e_invarg;
-               return;
-           }
-           else
-               tab_number = getdigits(&p);
-       }
-       else
-       {
-           if (*p != NUL)
-               tab_number = getdigits(&p);
-           else
-               tab_number = 1;
-           tab_number = tab_number * relative + tabpage_index(curtab);
-           if (relative == -1)
-               --tab_number;
-       }
-    }
-    else if (eap->addr_count != 0)
-    {
-       tab_number = eap->line2;
-       if (**eap->cmdlinep == '-')
-           --tab_number;
-    }
-    else
-       tab_number = LAST_TAB_NR;
-
-    tabpage_move(tab_number);
+    tab_number = get_tabpage_arg(eap);
+    if (eap->errmsg == NULL)
+       tabpage_move(tab_number);
 }
 
 /*
index 1720107458687bfc599618f27dcdc471e9aa1d24..c139958df34143d967e0d5312dee499be7cc5593 100644 (file)
@@ -94,10 +94,6 @@ function Test_tabpage()
   call assert_equal(7, tabpagenr())
   tabmove
   call assert_equal(10, tabpagenr())
-  tabmove -20
-  call assert_equal(1, tabpagenr())
-  tabmove +20
-  call assert_equal(10, tabpagenr())
   0tabmove
   call assert_equal(1, tabpagenr())
   $tabmove
@@ -110,7 +106,16 @@ function Test_tabpage()
   call assert_equal(4, tabpagenr())
   7tabmove 5
   call assert_equal(5, tabpagenr())
+  call assert_fails("99tabmove", 'E16:')
+  call assert_fails("+99tabmove", 'E16:')
+  call assert_fails("-99tabmove", 'E16:')
   call assert_fails("tabmove foo", 'E474:')
+  call assert_fails("tabmove 99", 'E474:')
+  call assert_fails("tabmove +99", 'E474:')
+  call assert_fails("tabmove -99", 'E474:')
+  call assert_fails("tabmove -3+", 'E474:')
+  call assert_fails("tabmove $3", 'E474:')
+  1tabonly!
 endfunc
 
 " Test autocommands
@@ -118,7 +123,6 @@ function Test_tabpage_with_autocmd()
   if !has('autocmd')
     return
   endif
-  tabonly!
   command -nargs=1 -bar C :call add(s:li, '=== ' . <q-args> . ' ===')|<args>
   augroup TestTabpageGroup
     au!
@@ -183,8 +187,10 @@ function Test_tabpage_with_autocmd()
 
   autocmd TabDestructive TabEnter * nested :C tabnext 2 | C tabclose 3
   let s:li = []
-  C tabnext 3
-  call assert_equal(['=== tabnext 3 ===', 'BufLeave', 'WinLeave', 'TabLeave', 'WinEnter', 'TabEnter', '=== tabnext 2 ===', 'BufLeave', 'WinLeave', 'TabLeave', 'WinEnter', 'TabEnter', '=== tabnext 2 ===', '=== tabclose 3 ===', 'BufEnter', '=== tabclose 3 ==='], s:li)
+  call assert_equal(3, tabpagenr('$'))
+  C tabnext 2
+  call assert_equal(2, tabpagenr('$'))
+  call assert_equal(['=== tabnext 2 ===', 'WinLeave', 'TabLeave', 'WinEnter', 'TabEnter', '=== tabnext 2 ===', '=== tabclose 3 ==='], s:li)
   call assert_equal(['2/2'], [tabpagenr().'/'.tabpagenr('$')])
 
   delcommand C
@@ -192,8 +198,7 @@ function Test_tabpage_with_autocmd()
   augroup! TabDestructive
   autocmd! TestTabpageGroup
   augroup! TestTabpageGroup
-  tabonly!
-  bw!
+  1tabonly!
 endfunction
 
 function Test_tabpage_with_tab_modifier()
@@ -224,8 +229,223 @@ function Test_tabpage_with_tab_modifier()
   call assert_fails('-99tab help', 'E16:')
 
   delfunction s:check_tab
-  tabonly!
-  bw!
+  1tabonly!
+endfunction
+
+function Check_tab_count(pre_nr, cmd, post_nr)
+  exec 'tabnext' a:pre_nr
+  normal! G
+  exec a:cmd
+  call assert_equal(a:post_nr, tabpagenr(), a:cmd)
+endfunc
+
+" Test for [count] of tabnext
+function Test_tabpage_with_tabnext()
+  for n in range(4)
+    tabedit
+    call setline(1, ['', '', '3'])
+  endfor
+
+  call Check_tab_count(1, 'tabnext', 2)
+  call Check_tab_count(1, '3tabnext', 3)
+  call Check_tab_count(1, '.tabnext', 1)
+  call Check_tab_count(1, '.+1tabnext', 2)
+  call Check_tab_count(2, '+tabnext', 3)
+  call Check_tab_count(2, '+2tabnext', 4)
+  call Check_tab_count(4, '-tabnext', 3)
+  call Check_tab_count(4, '-2tabnext', 2)
+  call Check_tab_count(3, '$tabnext', 5)
+  call assert_fails('0tabnext', 'E16:')
+  call assert_fails('99tabnext', 'E16:')
+  call assert_fails('+99tabnext', 'E16:')
+  call assert_fails('-99tabnext', 'E16:')
+  call Check_tab_count(1, 'tabnext 3', 3)
+  call Check_tab_count(2, 'tabnext +', 3)
+  call Check_tab_count(2, 'tabnext +2', 4)
+  call Check_tab_count(4, 'tabnext -', 3)
+  call Check_tab_count(4, 'tabnext -2', 2)
+  call Check_tab_count(3, 'tabnext $', 5)
+  call assert_fails('tabnext 0', 'E474:')
+  call assert_fails('tabnext .', 'E474:')
+  call assert_fails('tabnext -+', 'E474:')
+  call assert_fails('tabnext +2-', 'E474:')
+  call assert_fails('tabnext $3', 'E474:')
+  call assert_fails('tabnext 99', 'E474:')
+  call assert_fails('tabnext +99', 'E474:')
+  call assert_fails('tabnext -99', 'E474:')
+
+  1tabonly!
+endfunction
+
+" Test for [count] of tabprevious
+function Test_tabpage_with_tabprevious()
+  for n in range(5)
+    tabedit
+    call setline(1, ['', '', '3'])
+  endfor
+
+  for cmd in ['tabNext', 'tabprevious']
+    call Check_tab_count(6, cmd, 5)
+    call Check_tab_count(6, '3' . cmd, 3)
+    call Check_tab_count(6, '8' . cmd, 4)
+    call Check_tab_count(6, cmd . ' 3', 3)
+    call Check_tab_count(6, cmd . ' 8', 4)
+    for n in range(2)
+      for c in ['0', '.+3', '+', '+2' , '-', '-2' , '$', '+99', '-99']
+        if n == 0 " pre count
+          let entire_cmd = c . cmd
+          let err_code = 'E16:'
+        else
+          let entire_cmd = cmd . ' ' . c
+          let err_code = 'E474:'
+        endif
+        call assert_fails(entire_cmd, err_code)
+      endfor
+    endfor
+  endfor
+
+  1tabonly!
+endfunction
+
+function s:reconstruct_tabpage_for_test(nr)
+  let n = (a:nr > 2) ? a:nr - 2 : 1
+  1tabonly!
+  0tabedit n0
+  for n in range(1, n)
+    exec '$tabedit n' . n
+    if n == 1
+      call setline(1, ['', '', '3'])
+    endif
+  endfor
+endfunc
+
+" Test for [count] of tabclose
+function Test_tabpage_with_tabclose()
+
+  " pre count
+  call s:reconstruct_tabpage_for_test(6)
+  call Check_tab_count(3, 'tabclose!', 3)
+  call Check_tab_count(1, '3tabclose', 1)
+  call Check_tab_count(4, '4tabclose', 3)
+  call Check_tab_count(3, '1tabclose', 2)
+  call Check_tab_count(2, 'tabclose', 1)
+  call assert_equal(1, tabpagenr('$'))
+  call assert_equal('', bufname(''))
+
+  call s:reconstruct_tabpage_for_test(6)
+  call Check_tab_count(2, '$tabclose', 2)
+  call Check_tab_count(4, '.tabclose', 4)
+  call Check_tab_count(3, '.+tabclose', 3)
+  call Check_tab_count(3, '.-2tabclose', 2)
+  call Check_tab_count(1, '.+1tabclose!', 1)
+  call assert_equal(1, tabpagenr('$'))
+  call assert_equal('', bufname(''))
+
+  " post count
+  call s:reconstruct_tabpage_for_test(6)
+  call Check_tab_count(3, 'tabclose!', 3)
+  call Check_tab_count(1, 'tabclose 3', 1)
+  call Check_tab_count(4, 'tabclose 4', 3)
+  call Check_tab_count(3, 'tabclose 1', 2)
+  call Check_tab_count(2, 'tabclose', 1)
+  call assert_equal(1, tabpagenr('$'))
+  call assert_equal('', bufname(''))
+
+  call s:reconstruct_tabpage_for_test(6)
+  call Check_tab_count(2, 'tabclose $', 2)
+  call Check_tab_count(4, 'tabclose', 4)
+  call Check_tab_count(3, 'tabclose +', 3)
+  call Check_tab_count(3, 'tabclose -2', 2)
+  call Check_tab_count(1, 'tabclose! +1', 1)
+  call assert_equal(1, tabpagenr('$'))
+  call assert_equal('', bufname(''))
+
+  call s:reconstruct_tabpage_for_test(6)
+  for n in range(2)
+    for c in ['0', '$3', '99', '+99', '-99']
+      if n == 0 " pre count
+        let entire_cmd = c . 'tabclose'
+        let err_code = 'E16:'
+      else
+        let entire_cmd = 'tabclose ' . c
+        let err_code = 'E474:'
+      endif
+      call assert_fails(entire_cmd, err_code)
+      call assert_equal(6, tabpagenr('$'))
+    endfor
+  endfor
+
+  call assert_fails('3tabclose', 'E37:')
+  call assert_fails('tabclose 3', 'E37:')
+  call assert_fails('tabclose -+', 'E474:')
+  call assert_fails('tabclose +2-', 'E474:')
+  call assert_equal(6, tabpagenr('$'))
+
+  1tabonly!
+endfunction
+
+" Test for [count] of tabonly
+function Test_tabpage_with_tabonly()
+
+  " Test for the normal behavior (pre count only)
+  let tc = [ [4, '.', '!'], [2, '.+', ''], [3, '.-2', '!'], [1, '.+1', '!'] ]
+  for c in tc
+    call s:reconstruct_tabpage_for_test(6)
+    let entire_cmd = c[1] . 'tabonly' . c[2]
+    call Check_tab_count(c[0], entire_cmd, 1)
+    call assert_equal(1, tabpagenr('$'))
+  endfor
+
+  " Test for the normal behavior
+  let tc2 = [ [3, '', ''], [1, '3', ''], [4, '4', '!'], [3, '1', '!'],
+        \    [2, '', '!'],
+        \    [2, '$', '!'], [3, '+', '!'], [3, '-2', '!'], [3, '+1', '!']
+        \  ]
+  for n in range(2)
+    for c in tc2
+      call s:reconstruct_tabpage_for_test(6)
+      if n == 0 " pre count
+        let entire_cmd = c[1] . 'tabonly' . c[2]
+      else
+        let entire_cmd = 'tabonly' . c[2] . ' ' . c[1]
+      endif
+      call Check_tab_count(c[0], entire_cmd, 1)
+      call assert_equal(1, tabpagenr('$'))
+    endfor
+  endfor
+
+  " Test for the error behavior
+  for n in range(2)
+    for c in ['0', '$3', '99', '+99', '-99']
+      call s:reconstruct_tabpage_for_test(6)
+      if n == 0 " pre count
+        let entire_cmd = c . 'tabonly'
+        let err_code = 'E16:'
+      else
+        let entire_cmd = 'tabonly ' . c
+        let err_code = 'E474:'
+      endif
+      call assert_fails(entire_cmd, err_code)
+      call assert_equal(6, tabpagenr('$'))
+    endfor
+  endfor
+
+  " Test for the error behavior (post count only)
+  for c in tc
+    call s:reconstruct_tabpage_for_test(6)
+    let entire_cmd = 'tabonly' . c[2] . ' ' . c[1]
+    let err_code = 'E474:'
+    call assert_fails(entire_cmd, err_code)
+    call assert_equal(6, tabpagenr('$'))
+  endfor
+
+  call assert_fails('tabonly -+', 'E474:')
+  call assert_fails('tabonly +2-', 'E474:')
+  call assert_equal(6, tabpagenr('$'))
+
+  1tabonly!
+  new
+  only!
 endfunction
 
 func Test_tabnext_on_buf_unload1()
index aaeb258ef97daf2f6dce22af0b73c0c6ca370315..05d2dd424debe20dffc059ad0d448455fc4a20f9 100644 (file)
@@ -764,6 +764,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    259,
 /**/
     258,
 /**/