patch 8.2.2344: using inclusive index for slice is not always desired
Problem: Using inclusive index for slice is not always desired.
Solution: Add the slice() method, which has an exclusive index. (closes
#7408)
diff --git a/src/vim9execute.c b/src/vim9execute.c
index 7c4ef2a..938fc2e 100644
--- a/src/vim9execute.c
+++ b/src/vim9execute.c
@@ -965,10 +965,11 @@
/*
* Return the slice "str[first:last]" using character indexes.
+ * "exclusive" is TRUE for slice().
* Return NULL when the result is empty.
*/
char_u *
-string_slice(char_u *str, varnumber_T first, varnumber_T last)
+string_slice(char_u *str, varnumber_T first, varnumber_T last, int exclusive)
{
long start_byte, end_byte;
size_t slen;
@@ -979,12 +980,12 @@
start_byte = char_idx2byte(str, slen, first);
if (start_byte < 0)
start_byte = 0; // first index very negative: use zero
- if (last == -1)
+ if ((last == -1 && !exclusive) || last == VARNUM_MAX)
end_byte = (long)slen;
else
{
end_byte = char_idx2byte(str, slen, last);
- if (end_byte >= 0 && end_byte < (long)slen)
+ if (!exclusive && end_byte >= 0 && end_byte < (long)slen)
// end index is inclusive
end_byte += MB_CPTR2LEN(str + end_byte);
}
@@ -2992,7 +2993,7 @@
tv = STACK_TV_BOT(-1);
if (is_slice)
// Slice: Select the characters from the string
- res = string_slice(tv->vval.v_string, n1, n2);
+ res = string_slice(tv->vval.v_string, n1, n2, FALSE);
else
// Index: The resulting variable is a string of a
// single character. If the index is too big or
@@ -3030,8 +3031,8 @@
ectx.ec_stack.ga_len -= is_slice ? 2 : 1;
tv = STACK_TV_BOT(-1);
SOURCING_LNUM = iptr->isn_lnum;
- if (list_slice_or_index(list, is_slice, n1, n2, tv, TRUE)
- == FAIL)
+ if (list_slice_or_index(list, is_slice, n1, n2, FALSE,
+ tv, TRUE) == FAIL)
goto on_error;
}
break;
@@ -3052,8 +3053,8 @@
goto on_error;
var1 = is_slice ? STACK_TV_BOT(-2) : STACK_TV_BOT(-1);
var2 = is_slice ? STACK_TV_BOT(-1) : NULL;
- res = eval_index_inner(tv, is_slice,
- var1, var2, NULL, -1, TRUE);
+ res = eval_index_inner(tv, is_slice, var1, var2,
+ FALSE, NULL, -1, TRUE);
clear_tv(var1);
if (is_slice)
clear_tv(var2);