neovim

Neovim text editor
git clone https://git.dasho.dev/neovim.git
Log | Files | Refs | README

commit f5cefd70e4f8796e82e6e42b6f50fa6fad0c36c3
parent dd3d857c390bee1f467eda9ec82c29948672bbff
Author: zeertzjq <zeertzjq@outlook.com>
Date:   Thu,  4 May 2023 17:16:31 +0800

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>

Diffstat:
Msrc/nvim/eval.c | 52++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 52 insertions(+), 0 deletions(-)

diff --git 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