mirror of
https://github.com/neovim/neovim.git
synced 2026-11-02 09:49:02 -06:00
vim-patch:9.2.0812: :argdelete with pattern leads to wrong argidx() (#40876)
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: vim/vim#20697
https://github.com/vim/vim/commit/3b40a14a46c2e4f2a29dbf0b2fe48260ce2166ab
This commit is contained in:
1 parent
16c145d240
commit
60b643a815
2 files changed
+50
-20
No files matched your search
+24
-19
@@ -375,7 +375,7 @@ static void arglist_del_files(garray_T *alist_ga)
|
||||
xfree(ARGLIST[match].ae_fname);
|
||||
memmove(ARGLIST + match, ARGLIST + match + 1,
|
||||
(size_t)(ARGCOUNT - match - 1) * sizeof(aentry_T));
|
||||
ALIST(curwin)->al_ga.ga_len--;
|
||||
ARGCOUNT--;
|
||||
if (curwin->w_arg_idx > match) {
|
||||
curwin->w_arg_idx--;
|
||||
}
|
||||
@@ -780,32 +780,37 @@ void ex_argdelete(exarg_T *eap)
|
||||
if (*eap->arg != NUL) {
|
||||
// Can't have both a range and an argument.
|
||||
emsg(_(e_invarg));
|
||||
} 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_invrange));
|
||||
}
|
||||
} else {
|
||||
for (linenr_T i = eap->line1; i <= eap->line2; i++) {
|
||||
xfree(ARGLIST[i - 1].ae_fname);
|
||||
}
|
||||
memmove(ARGLIST + eap->line1 - 1, ARGLIST + eap->line2,
|
||||
(size_t)(ARGCOUNT - eap->line2) * sizeof(aentry_T));
|
||||
ALIST(curwin)->al_ga.ga_len -= (int)n;
|
||||
if (curwin->w_arg_idx >= eap->line2) {
|
||||
curwin->w_arg_idx -= (int)n;
|
||||
} else if (curwin->w_arg_idx > eap->line1) {
|
||||
curwin->w_arg_idx = (int)eap->line1;
|
||||
}
|
||||
if (ARGCOUNT == 0) {
|
||||
curwin->w_arg_idx = 0;
|
||||
} else if (curwin->w_arg_idx >= ARGCOUNT) {
|
||||
curwin->w_arg_idx = ARGCOUNT - 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
for (linenr_T i = eap->line1; i <= eap->line2; i++) {
|
||||
xfree(ARGLIST[i - 1].ae_fname);
|
||||
}
|
||||
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();
|
||||
}
|
||||
|
||||
|
||||
@@ -462,15 +462,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
|
||||
|
||||
Reference in new issue
Block a user