Mercurial > vim
diff src/eval.c @ 23604:1816ea68c022 v8.2.2344
patch 8.2.2344: using inclusive index for slice is not always desired
Commit: https://github.com/vim/vim/commit/6601b62943a19d4f8818c3638440663d67a17b6a
Author: Bram Moolenaar <Bram@vim.org>
Date: Wed Jan 13 21:47:15 2021 +0100
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)
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Wed, 13 Jan 2021 22:00:04 +0100 |
parents | f4347a61ed38 |
children | b26bbc03126a |
line wrap: on
line diff
--- a/src/eval.c +++ b/src/eval.c @@ -3877,8 +3877,9 @@ eval_index( if (evaluate) { int res = eval_index_inner(rettv, range, - empty1 ? NULL : &var1, empty2 ? NULL : &var2, + empty1 ? NULL : &var1, empty2 ? NULL : &var2, FALSE, key, keylen, verbose); + if (!empty1) clear_tv(&var1); if (range) @@ -3938,9 +3939,26 @@ check_can_index(typval_T *rettv, int eva } /* + * slice() function + */ + void +f_slice(typval_T *argvars, typval_T *rettv) +{ + if (check_can_index(argvars, TRUE, FALSE) == OK) + { + copy_tv(argvars, rettv); + eval_index_inner(rettv, TRUE, argvars + 1, + argvars[2].v_type == VAR_UNKNOWN ? NULL : argvars + 2, + TRUE, NULL, 0, FALSE); + } +} + +/* * Apply index or range to "rettv". * "var1" is the first index, NULL for [:expr]. * "var2" is the second index, NULL for [expr] and [expr: ] + * "exclusive" is TRUE for slice(): second index is exclusive, use character + * index for string. * Alternatively, "key" is not NULL, then key[keylen] is the dict index. */ int @@ -3949,12 +3967,13 @@ eval_index_inner( int is_range, typval_T *var1, typval_T *var2, + int exclusive, char_u *key, int keylen, int verbose) { - long n1, n2 = 0; - long len; + varnumber_T n1, n2 = 0; + long len; n1 = 0; if (var1 != NULL && rettv->v_type != VAR_DICT) @@ -3968,10 +3987,10 @@ eval_index_inner( emsg(_(e_cannot_slice_dictionary)); return FAIL; } - if (var2 == NULL) - n2 = -1; + if (var2 != NULL) + n2 = tv_get_number(var2); else - n2 = tv_get_number(var2); + n2 = VARNUM_MAX; } switch (rettv->v_type) @@ -3994,10 +4013,10 @@ eval_index_inner( char_u *s = tv_get_string(rettv); len = (long)STRLEN(s); - if (in_vim9script()) + if (in_vim9script() || exclusive) { if (is_range) - s = string_slice(s, n1, n2); + s = string_slice(s, n1, n2, exclusive); else s = char_from_string(s, n1); } @@ -4015,6 +4034,8 @@ eval_index_inner( n2 = len + n2; else if (n2 >= len) n2 = len; + if (exclusive) + --n2; if (n1 >= len || n2 < 0 || n1 > n2) s = NULL; else @@ -4051,7 +4072,9 @@ eval_index_inner( if (n2 < 0) n2 = len + n2; else if (n2 >= len) - n2 = len - 1; + n2 = len - (exclusive ? 0 : 1); + if (exclusive) + --n2; if (n1 >= len || n2 < 0 || n1 > n2) { clear_tv(rettv); @@ -4103,9 +4126,9 @@ eval_index_inner( if (var1 == NULL) n1 = 0; if (var2 == NULL) - n2 = -1; + n2 = VARNUM_MAX; if (list_slice_or_index(rettv->vval.v_list, - is_range, n1, n2, rettv, verbose) == FAIL) + is_range, n1, n2, exclusive, rettv, verbose) == FAIL) return FAIL; break;