diff options
author | zeertzjq <zeertzjq@outlook.com> | 2023-05-04 17:16:31 +0800 |
---|---|---|
committer | zeertzjq <zeertzjq@outlook.com> | 2023-05-04 17:20:53 +0800 |
commit | f5cefd70e4f8796e82e6e42b6f50fa6fad0c36c3 (patch) | |
tree | dc95f8b99ea86251f0593c11dd5c9f300e654b27 | |
parent | dd3d857c390bee1f467eda9ec82c29948672bbff (diff) | |
download | rneovim-f5cefd70e4f8796e82e6e42b6f50fa6fad0c36c3.tar.gz rneovim-f5cefd70e4f8796e82e6e42b6f50fa6fad0c36c3.tar.bz2 rneovim-f5cefd70e4f8796e82e6e42b6f50fa6fad0c36c3.zip |
vim-patch:8.2.1462: Vim9: string slice not supported yet
Problem: Vim9: string slice not supported yet.
Solution: Add support for string slicing.
https://github.com/vim/vim/commit/11107bab7ead9124f46a7ddf6aa3bb66b43a8246
Co-authored-by: Bram Moolenaar <Bram@vim.org>
-rw-r--r-- | src/nvim/eval.c | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/src/nvim/eval.c b/src/nvim/eval.c index b06c102e2c..0a41ffd4bf 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -7285,6 +7285,58 @@ char *char_from_string(char *str, varnumber_T index) return xstrnsave(str + nbyte, (size_t)utf_ptr2len(str + nbyte)); } +/// Get the byte index for character index "idx" in string "str" with length +/// "str_len". +/// 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 zero. +static size_t char_idx2byte(char *str, size_t str_len, varnumber_T idx) +{ + varnumber_T nchar = idx; + size_t nbyte = 0; + + if (nchar >= 0) { + while (nchar > 0 && nbyte < str_len) { + nbyte += (size_t)utf_ptr2len(str + nbyte); + nchar--; + } + } else { + nbyte = str_len; + while (nchar < 0 && nbyte > 0) { + nbyte--; + nbyte -= (size_t)utf_head_off(str, str + nbyte); + nchar++; + } + } + return nbyte; +} + +/// Return the slice "str[first:last]" using character indexes. +/// Return NULL when the result is empty. +char *string_slice(char *str, varnumber_T first, varnumber_T last) +{ + if (str == NULL) { + return NULL; + } + size_t slen = strlen(str); + size_t start_byte = char_idx2byte(str, slen, first); + size_t end_byte; + if (last == -1) { + end_byte = slen; + } else { + end_byte = char_idx2byte(str, slen, last); + if (end_byte < slen) { + // end index is inclusive + end_byte += (size_t)utf_ptr2len(str + end_byte); + } + } + + if (start_byte >= slen || end_byte <= start_byte) { + return NULL; + } + return xstrnsave(str + start_byte, end_byte - start_byte); +} + /// Handle: /// - expr[expr], expr[expr:expr] subscript /// - ".name" lookup |