]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.2.0812: :argdelete with pattern leads to wrong argidx() v9.2.0812
authorzeertzjq <zeertzjq@outlook.com>
Mon, 20 Jul 2026 15:19:20 +0000 (15:19 +0000)
committerChristian Brabandt <cb@256bit.org>
Mon, 20 Jul 2026 15:19:20 +0000 (15:19 +0000)
Problem:  :argdelete with pattern leads to wrong argidx().
Solution: Correct argidx() in both branches of ex_argdelete().  Also use
          ARGCOUNT macro in two more places (zeertzjq).

related: patch 7.4.1119
related: neovim/neovim#40564
closes:  #20697

Signed-off-by: zeertzjq <zeertzjq@outlook.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
src/arglist.c
src/testdir/test_arglist.vim
src/version.c

index 84de912f01c171abae80803fa469cb7dfc297d4f..80e91475a95ecfec7051fc9e83ca0db9107876ce 100644 (file)
@@ -429,7 +429,7 @@ arglist_del_files(garray_T *alist_ga)
                vim_free(ARGLIST[match].ae_fname);
                mch_memmove(ARGLIST + match, ARGLIST + match + 1,
                        (ARGCOUNT - match - 1) * sizeof(aentry_T));
-               --ALIST(curwin)->al_ga.ga_len;
+               --ARGCOUNT;
                if (curwin->w_arg_idx > match)
                    --curwin->w_arg_idx;
                --match;
@@ -900,33 +900,37 @@ ex_argdelete(exarg_T *eap)
            eap->line2 = ARGCOUNT;
        n = eap->line2 - eap->line1 + 1;
        if (*eap->arg != NUL)
+       {
            // Can't have both a range and an argument.
            emsg(_(e_invalid_argument));
-       else if (n <= 0)
+           return;
+       }
+       if (n <= 0)
        {
            // Don't give an error for ":%argdel" if the list is empty.
            if (eap->line1 != 1 || eap->line2 != 0)
                emsg(_(e_invalid_range));
+           return;
        }
-       else
-       {
-           for (i = eap->line1; i <= eap->line2; ++i)
-               vim_free(ARGLIST[i - 1].ae_fname);
-           mch_memmove(ARGLIST + eap->line1 - 1, ARGLIST + eap->line2,
-                       (size_t)((ARGCOUNT - eap->line2) * sizeof(aentry_T)));
-           ALIST(curwin)->al_ga.ga_len -= n;
-           if (curwin->w_arg_idx >= eap->line2)
-               curwin->w_arg_idx -= n;
-           else if (curwin->w_arg_idx > eap->line1)
-               curwin->w_arg_idx = eap->line1;
-           if (ARGCOUNT == 0)
-               curwin->w_arg_idx = 0;
-           else if (curwin->w_arg_idx >= ARGCOUNT)
-               curwin->w_arg_idx = ARGCOUNT - 1;
-       }
+
+       for (i = eap->line1; i <= eap->line2; ++i)
+           vim_free(ARGLIST[i - 1].ae_fname);
+       mch_memmove(ARGLIST + eap->line1 - 1, ARGLIST + eap->line2,
+                   (size_t)((ARGCOUNT - eap->line2) * sizeof(aentry_T)));
+       ARGCOUNT -= n;
+       if (curwin->w_arg_idx >= eap->line2)
+           curwin->w_arg_idx -= n;
+       else if (curwin->w_arg_idx > eap->line1)
+           curwin->w_arg_idx = eap->line1;
     }
     else
        do_arglist(eap->arg, AL_DEL, 0, FALSE);
+
+    if (ARGCOUNT == 0)
+       curwin->w_arg_idx = 0;
+    else if (curwin->w_arg_idx >= ARGCOUNT)
+       curwin->w_arg_idx = ARGCOUNT - 1;
+
     maketitle();
 }
 
index f62d2cfabf31f616e06201b63faa38ad8b896e0a..9df54a19ddf8bc30856fbdf6d140bc49318bd897 100644 (file)
@@ -457,15 +457,40 @@ func Test_argdelete()
   args aa a aaa b bb
   argdelete a*
   call assert_equal(['b', 'bb'], argv())
+  call assert_equal(0, argidx())
   call assert_equal('aa', expand('%:t'))
   last
+  call assert_equal(1, argidx())
+  call assert_equal('bb', expand('%:t'))
   argdelete %
   call assert_equal(['b'], argv())
-  call assert_fails('argdelete', 'E610:')
+  call assert_equal(0, argidx())
+  call assert_equal('bb', expand('%:t'))
+
   call assert_fails('1,100argdelete', 'E16:')
   call assert_fails('argdel /\)/', 'E55:')
   call assert_fails('1argdel 1', 'E474:')
 
+  call Reset_arglist()
+  args aa a aaa b bb
+  4argument
+  call assert_equal(3, argidx())
+  call assert_equal('b', expand('%:t'))
+  argdelete aa*
+  call assert_equal(['a', 'b', 'bb'], argv())
+  call assert_equal(1, argidx())
+  call assert_equal('b', expand('%:t'))
+  2argdelete
+  call assert_equal(['a', 'bb'], argv())
+  call assert_equal(1, argidx())
+  call assert_equal('b', expand('%:t'))
+  %argdelete
+  call assert_equal([], argv())
+  call assert_equal(0, argidx())
+  call assert_equal('b', expand('%:t'))
+  " :%argdelete when the arglist is already empty should not error
+  %argdelete
+
   call Reset_arglist()
   args a b c d
   next
index e523f6dad4cad63de99e38b6ea982717180a70bc..333bbc87d8b3f8ba65b7d7d360949e2e9568cc37 100644 (file)
@@ -759,6 +759,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    812,
 /**/
     811,
 /**/