1
0
forked from aniani/vim

patch 8.2.2318: Vim9: string and list index work differently

Problem:    Vim9: string and list index work differently.
Solution:   Make string index work like list index. (closes #7643)
This commit is contained in:
Bram Moolenaar
2021-01-09 13:20:37 +01:00
parent 9e0f883f89
commit e7525c5520
7 changed files with 121 additions and 101 deletions

View File

@@ -5548,97 +5548,6 @@ eval_isdictc(int c)
return ASCII_ISALNUM(c) || c == '_';
}
/*
* Return the character "str[index]" where "index" is the character index. If
* "index" is out of range NULL is returned.
*/
char_u *
char_from_string(char_u *str, varnumber_T index)
{
size_t nbyte = 0;
varnumber_T nchar = index;
size_t slen;
if (str == NULL || index < 0)
return NULL;
slen = STRLEN(str);
while (nchar > 0 && nbyte < slen)
{
nbyte += MB_CPTR2LEN(str + nbyte);
--nchar;
}
if (nbyte >= slen)
return NULL;
return vim_strnsave(str + nbyte, MB_CPTR2LEN(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 -1.
*/
static long
char_idx2byte(char_u *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 += MB_CPTR2LEN(str + nbyte);
--nchar;
}
}
else
{
nbyte = str_len;
while (nchar < 0 && nbyte > 0)
{
--nbyte;
nbyte -= mb_head_off(str, str + nbyte);
++nchar;
}
if (nchar < 0)
return -1;
}
return (long)nbyte;
}
/*
* Return the slice "str[first:last]" using character indexes.
* Return NULL when the result is empty.
*/
char_u *
string_slice(char_u *str, varnumber_T first, varnumber_T last)
{
long start_byte, end_byte;
size_t slen;
if (str == NULL)
return NULL;
slen = STRLEN(str);
start_byte = char_idx2byte(str, slen, first);
if (start_byte < 0)
start_byte = 0; // first index very negative: use zero
if (last == -1)
end_byte = (long)slen;
else
{
end_byte = char_idx2byte(str, slen, last);
if (end_byte >= 0 && end_byte < (long)slen)
// end index is inclusive
end_byte += MB_CPTR2LEN(str + end_byte);
}
if (start_byte >= (long)slen || end_byte <= start_byte)
return NULL;
return vim_strnsave(str + start_byte, end_byte - start_byte);
}
/*
* Handle:
* - expr[expr], expr[expr:expr] subscript