aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/eval/vars.c
diff options
context:
space:
mode:
authorzeertzjq <zeertzjq@outlook.com>2023-06-12 15:38:53 +0800
committerzeertzjq <zeertzjq@outlook.com>2023-06-12 17:20:55 +0800
commita0cb53eca7a04326dd857cf33fac1154aff7773a (patch)
tree73d0046d0cd7752b0503e60b5c55cd1f0b512bbc /src/nvim/eval/vars.c
parent551cc3a2a3e2ee180234910cbe2ef81bd37508de (diff)
downloadrneovim-a0cb53eca7a04326dd857cf33fac1154aff7773a.tar.gz
rneovim-a0cb53eca7a04326dd857cf33fac1154aff7773a.tar.bz2
rneovim-a0cb53eca7a04326dd857cf33fac1154aff7773a.zip
vim-patch:8.2.2533: Vim9: cannot use a range with :unlet
Problem: Vim9: cannot use a range with :unlet. Solution: Implement ISN_UNLETRANGE. https://github.com/vim/vim/commit/5b5ae29bd3d7b832b6f15320430f7f191e0abd1f Co-authored-by: Bram Moolenaar <Bram@vim.org>
Diffstat (limited to 'src/nvim/eval/vars.c')
-rw-r--r--src/nvim/eval/vars.c46
1 files changed, 28 insertions, 18 deletions
diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c
index 0663c3c54c..f988a49e6c 100644
--- a/src/nvim/eval/vars.c
+++ b/src/nvim/eval/vars.c
@@ -1056,25 +1056,10 @@ static int do_unlet_var(lval_T *lp, char *name_end, exarg_T *eap, int deep FUNC_
lp->ll_name_len))) {
return FAIL;
} else if (lp->ll_range) {
- assert(lp->ll_list != NULL);
- // Delete a range of List items.
- listitem_T *const first_li = lp->ll_li;
- listitem_T *last_li = first_li;
- while (true) {
- listitem_T *const li = TV_LIST_ITEM_NEXT(lp->ll_list, lp->ll_li);
- if (value_check_lock(TV_LIST_ITEM_TV(lp->ll_li)->v_lock,
- lp->ll_name,
- lp->ll_name_len)) {
- return false;
- }
- lp->ll_li = li;
- lp->ll_n1++;
- if (lp->ll_li == NULL || (!lp->ll_empty2 && lp->ll_n2 < lp->ll_n1)) {
- break;
- }
- last_li = lp->ll_li;
+ if (list_unlet_range(lp->ll_list, lp->ll_li, lp->ll_name, lp->ll_name_len,
+ lp->ll_n1, !lp->ll_empty2, lp->ll_n2) == FAIL) {
+ return FAIL;
}
- tv_list_remove_items(lp->ll_list, first_li, last_li);
} else {
if (lp->ll_list != NULL) {
// unlet a List item.
@@ -1107,6 +1092,31 @@ static int do_unlet_var(lval_T *lp, char *name_end, exarg_T *eap, int deep FUNC_
return ret;
}
+/// Unlet one item or a range of items from a list.
+/// Return OK or FAIL.
+static int list_unlet_range(list_T *const l, listitem_T *const li_first, const char *const name,
+ const size_t name_len, const long n1_arg, const bool has_n2,
+ const long n2)
+{
+ assert(l != NULL);
+ // Delete a range of List items.
+ listitem_T *li_last = li_first;
+ long n1 = n1_arg;
+ while (true) {
+ if (value_check_lock(TV_LIST_ITEM_TV(li_last)->v_lock, name, name_len)) {
+ return FAIL;
+ }
+ listitem_T *const li = TV_LIST_ITEM_NEXT(l, li_last);
+ n1++;
+ if (li == NULL || (has_n2 && n2 < n1)) {
+ break;
+ }
+ li_last = li;
+ }
+ tv_list_remove_items(l, li_first, li_last);
+ return OK;
+}
+
/// unlet a variable
///
/// @param[in] name Variable name to unlet.