diff options
author | zeertzjq <zeertzjq@outlook.com> | 2023-05-04 16:46:38 +0800 |
---|---|---|
committer | zeertzjq <zeertzjq@outlook.com> | 2023-05-04 17:40:29 +0800 |
commit | b441dafdf53e367c7d43177274bd781c5c73e6e0 (patch) | |
tree | 4c8838192ce80a1ed652dd5bbda3c265678cdbea /src | |
parent | 62351ff3d2fba336f09569d844a7b6f7f36a078d (diff) | |
download | rneovim-b441dafdf53e367c7d43177274bd781c5c73e6e0.tar.gz rneovim-b441dafdf53e367c7d43177274bd781c5c73e6e0.tar.bz2 rneovim-b441dafdf53e367c7d43177274bd781c5c73e6e0.zip |
vim-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
vim/vim#7408)
https://github.com/vim/vim/commit/6601b62943a19d4f8818c3638440663d67a17b6a
Cherry-pick a line in docs added later.
Co-authored-by: Bram Moolenaar <Bram@vim.org>
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/eval.c | 79 | ||||
-rw-r--r-- | src/nvim/eval.lua | 1 | ||||
-rw-r--r-- | src/nvim/eval/typval.c | 21 | ||||
-rw-r--r-- | src/nvim/generators/gen_eval.lua | 1 |
4 files changed, 68 insertions, 34 deletions
diff --git a/src/nvim/eval.c b/src/nvim/eval.c index a14b098caf..930cda4bd4 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -1692,7 +1692,7 @@ void set_var_lval(lval_T *lp, char *endp, typval_T *rettv, int copy, const bool lp->ll_n2 = tv_blob_len(lp->ll_blob) - 1; } - if (tv_blob_set_range(lp->ll_blob, (int)lp->ll_n1, (int)lp->ll_n2, rettv) == FAIL) { + if (tv_blob_set_range(lp->ll_blob, lp->ll_n1, lp->ll_n2, rettv) == FAIL) { return; } } else { @@ -3542,7 +3542,7 @@ static int eval_index(char **arg, typval_T *rettv, evalarg_T *const evalarg, boo 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) { tv_clear(&var1); @@ -3592,17 +3592,31 @@ static int check_can_index(typval_T *rettv, bool evaluate, bool verbose) return OK; } +/// slice() function +void f_slice(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + if (check_can_index(argvars, true, false) == OK) { + tv_copy(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: ] +/// +/// @param var1 the first index, NULL for [:expr]. +/// @param var2 the second index, NULL for [expr] and [expr: ] +/// @param exclusive true for slice(): second index is exclusive, use character +/// index for string. /// Alternatively, "key" is not NULL, then key[keylen] is the dict index. static int eval_index_inner(typval_T *rettv, bool is_range, typval_T *var1, typval_T *var2, - const char *key, ptrdiff_t keylen, bool verbose) + bool exclusive, const char *key, ptrdiff_t keylen, bool verbose) { - int n1 = 0; - int n2 = 0; + varnumber_T n1 = 0; + varnumber_T n2 = 0; if (var1 != NULL && rettv->v_type != VAR_DICT) { - n1 = (int)tv_get_number(var1); + n1 = tv_get_number(var1); } if (is_range) { @@ -3612,10 +3626,10 @@ static int eval_index_inner(typval_T *rettv, bool is_range, typval_T *var1, typv } return FAIL; } - if (var2 == NULL) { - n2 = -1; + if (var2 != NULL) { + n2 = tv_get_number(var2); } else { - n2 = (int)tv_get_number(var2); + n2 = VARNUMBER_MAX; } } @@ -3632,7 +3646,13 @@ static int eval_index_inner(typval_T *rettv, bool is_range, typval_T *var1, typv const char *const s = tv_get_string(rettv); char *v; int len = (int)strlen(s); - if (is_range) { + if (exclusive) { + if (is_range) { + v = string_slice(s, n1, n2, exclusive); + } else { + v = char_from_string(s, n1); + } + } else if (is_range) { // The resulting variable is a substring. If the indexes // are out of range the result is empty. if (n1 < 0) { @@ -3646,6 +3666,9 @@ static int eval_index_inner(typval_T *rettv, bool is_range, typval_T *var1, typv } else if (n2 >= len) { n2 = len; } + if (exclusive) { + n2--; + } if (n1 >= len || n2 < 0 || n1 > n2) { v = NULL; } else { @@ -3680,7 +3703,10 @@ static int eval_index_inner(typval_T *rettv, bool is_range, typval_T *var1, typv 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) { tv_clear(rettv); @@ -3688,10 +3714,10 @@ static int eval_index_inner(typval_T *rettv, bool is_range, typval_T *var1, typv rettv->vval.v_blob = NULL; } else { blob_T *const blob = tv_blob_alloc(); - ga_grow(&blob->bv_ga, n2 - n1 + 1); - blob->bv_ga.ga_len = n2 - n1 + 1; - for (int i = n1; i <= n2; i++) { - tv_blob_set(blob, i - n1, tv_blob_get(rettv->vval.v_blob, i)); + ga_grow(&blob->bv_ga, (int)(n2 - n1 + 1)); + blob->bv_ga.ga_len = (int)(n2 - n1 + 1); + for (int i = (int)n1; i <= (int)n2; i++) { + tv_blob_set(blob, i - (int)n1, tv_blob_get(rettv->vval.v_blob, i)); } tv_clear(rettv); tv_blob_set_ret(rettv, blob); @@ -3703,7 +3729,7 @@ static int eval_index_inner(typval_T *rettv, bool is_range, typval_T *var1, typv n1 = len + n1; } if (n1 < len && n1 >= 0) { - const int v = (int)tv_blob_get(rettv->vval.v_blob, n1); + const int v = (int)tv_blob_get(rettv->vval.v_blob, (int)n1); tv_clear(rettv); rettv->v_type = VAR_NUMBER; rettv->vval.v_number = v; @@ -3718,10 +3744,10 @@ static int eval_index_inner(typval_T *rettv, bool is_range, typval_T *var1, typv n1 = 0; } if (var2 == NULL) { - n2 = -1; + n2 = VARNUMBER_MAX; } if (tv_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; @@ -7266,7 +7292,7 @@ int check_luafunc_name(const char *const str, const bool paren) /// Return the character "str[index]" where "index" is the character index. If /// "index" is out of range NULL is returned. -char *char_from_string(char *str, varnumber_T index) +char *char_from_string(const char *str, varnumber_T index) { size_t nbyte = 0; varnumber_T nchar = index; @@ -7290,7 +7316,7 @@ char *char_from_string(char *str, varnumber_T index) /// If going over the end return "str_len". /// If "idx" is negative count from the end, -1 is the last character. /// When going over the start return -1. -static ssize_t char_idx2byte(char *str, size_t str_len, varnumber_T idx) +static ssize_t char_idx2byte(const char *str, size_t str_len, varnumber_T idx) { varnumber_T nchar = idx; size_t nbyte = 0; @@ -7315,8 +7341,11 @@ static ssize_t char_idx2byte(char *str, size_t str_len, varnumber_T idx) } /// Return the slice "str[first:last]" using character indexes. +/// +/// @param exclusive true for slice(). +/// /// Return NULL when the result is empty. -char *string_slice(char *str, varnumber_T first, varnumber_T last) +char *string_slice(const char *str, varnumber_T first, varnumber_T last, bool exclusive) { if (str == NULL) { return NULL; @@ -7327,11 +7356,11 @@ char *string_slice(char *str, varnumber_T first, varnumber_T last) start_byte = 0; // first index very negative: use zero } ssize_t end_byte; - if (last == -1) { + if ((last == -1 && !exclusive) || last == VARNUMBER_MAX) { end_byte = (ssize_t)slen; } else { end_byte = char_idx2byte(str, slen, last); - if (end_byte >= 0 && end_byte < (ssize_t)slen) { + if (!exclusive && end_byte >= 0 && end_byte < (ssize_t)slen) { // end index is inclusive end_byte += utf_ptr2len(str + end_byte); } diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua index 09705148d0..aec5191249 100644 --- a/src/nvim/eval.lua +++ b/src/nvim/eval.lua @@ -371,6 +371,7 @@ return { simplify={args=1, base=1}, sin={args=1, base=1, float_func="sin"}, sinh={args=1, base=1, float_func="sinh"}, + slice={args={2, 3}, base=1}, sockconnect={args={2,3}}, sort={args={1, 3}, base=1}, soundfold={args=1, base=1}, diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 0b2be3074f..794debf771 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -765,10 +765,10 @@ int tv_list_concat(list_T *const l1, list_T *const l2, typval_T *const tv) return OK; } -static list_T *tv_list_slice(list_T *ol, int n1, int n2) +static list_T *tv_list_slice(list_T *ol, varnumber_T n1, varnumber_T n2) { list_T *l = tv_list_alloc(n2 - n1 + 1); - listitem_T *item = tv_list_find(ol, n1); + listitem_T *item = tv_list_find(ol, (int)n1); for (; n1 <= n2; n1++) { tv_list_append_tv(l, TV_LIST_ITEM_TV(item)); item = TV_LIST_ITEM_NEXT(rettv->vval.v_list, item); @@ -776,12 +776,12 @@ static list_T *tv_list_slice(list_T *ol, int n1, int n2) return l; } -int tv_list_slice_or_index(list_T *list, bool range, int n1_arg, int n2_arg, typval_T *rettv, - bool verbose) +int tv_list_slice_or_index(list_T *list, bool range, varnumber_T n1_arg, varnumber_T n2_arg, + bool exclusive, typval_T *rettv, bool verbose) { int len = tv_list_len(rettv->vval.v_list); - int n1 = n1_arg; - int n2 = n2_arg; + varnumber_T n1 = n1_arg; + varnumber_T n2 = n2_arg; if (n1 < 0) { n1 = len + n1; @@ -801,7 +801,10 @@ int tv_list_slice_or_index(list_T *list, bool range, int n1_arg, int n2_arg, typ if (n2 < 0) { n2 = len + n2; } else if (n2 >= len) { - n2 = len - 1; + n2 = len - (exclusive ? 0 : 1); + } + if (exclusive) { + n2--; } if (n2 < 0 || n2 + 1 < n1) { n2 = -1; @@ -2800,14 +2803,14 @@ int tv_blob_check_range(int bloblen, varnumber_T n1, varnumber_T n2, bool quiet) /// Set bytes "n1" to "n2" (inclusive) in "dest" to the value of "src". /// Caller must make sure "src" is a blob. /// Returns FAIL if the number of bytes does not match. -int tv_blob_set_range(blob_T *dest, int n1, int n2, typval_T *src) +int tv_blob_set_range(blob_T *dest, varnumber_T n1, varnumber_T n2, typval_T *src) { if (n2 - n1 + 1 != tv_blob_len(src->vval.v_blob)) { emsg(_("E972: Blob value does not have the right number of bytes")); return FAIL; } - for (int il = n1, ir = 0; il <= n2; il++) { + for (int il = (int)n1, ir = 0; il <= (int)n2; il++) { tv_blob_set(dest, il, tv_blob_get(src->vval.v_blob, ir++)); } return OK; diff --git a/src/nvim/generators/gen_eval.lua b/src/nvim/generators/gen_eval.lua index 7d531bc228..e93e9a8d02 100644 --- a/src/nvim/generators/gen_eval.lua +++ b/src/nvim/generators/gen_eval.lua @@ -17,6 +17,7 @@ hashpipe:write([[ #include "nvim/cmdexpand.h" #include "nvim/cmdhist.h" #include "nvim/digraph.h" +#include "nvim/eval.h" #include "nvim/eval/buffer.h" #include "nvim/eval/funcs.h" #include "nvim/eval/typval.h" |