aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzeertzjq <zeertzjq@outlook.com>2023-05-04 17:42:34 +0800
committerzeertzjq <zeertzjq@outlook.com>2023-05-04 17:49:56 +0800
commit3724e65c30f7d1ef803ac4e34eab7d4a9531b1a8 (patch)
tree6ddfb2294ae444c18f81f670500ea3f0f6fb5d88
parentb441dafdf53e367c7d43177274bd781c5c73e6e0 (diff)
downloadrneovim-3724e65c30f7d1ef803ac4e34eab7d4a9531b1a8.tar.gz
rneovim-3724e65c30f7d1ef803ac4e34eab7d4a9531b1a8.tar.bz2
rneovim-3724e65c30f7d1ef803ac4e34eab7d4a9531b1a8.zip
vim-patch:8.2.2607: strcharpart() cannot include composing characters
Problem: strcharpart() cannot include composing characters. Solution: Add the {skipcc} argument. https://github.com/vim/vim/commit/02b4d9b18a03549b68e364e428392b7a62766c74 Co-authored-by: Bram Moolenaar <Bram@vim.org>
-rw-r--r--runtime/doc/builtin.txt15
-rw-r--r--src/nvim/eval.lua2
-rw-r--r--src/nvim/strings.c22
-rw-r--r--test/old/testdir/test_expr_utf8.vim10
4 files changed, 41 insertions, 8 deletions
diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt
index 5be9ba910b..c2dc5ddd5b 100644
--- a/runtime/doc/builtin.txt
+++ b/runtime/doc/builtin.txt
@@ -486,7 +486,7 @@ str2list({expr} [, {utf8}]) List convert each character of {expr} to
str2nr({expr} [, {base} [, {quoted}]])
Number convert String to Number
strcharlen({expr}) Number character length of the String {expr}
-strcharpart({str}, {start} [, {len}])
+strcharpart({str}, {start} [, {len} [, {skipcc}]])
String {len} characters of {str} at
character {start}
strchars({expr} [, {skipcc}]) Number character count of the String {expr}
@@ -7779,6 +7779,7 @@ slice({expr}, {start} [, {end}]) *slice()*
Similar to using a |slice| "expr[start : end]", but "end" is
used exclusive. And for a string the indexes are used as
character indexes instead of byte indexes.
+ Also, composing characters are not counted.
When {end} is omitted the slice continues to the last item.
When {end} is -1 the last item is omitted.
Returns an empty value if {start} or {end} are invalid.
@@ -8129,12 +8130,16 @@ strcharlen({string}) *strcharlen()*
GetText()->strcharlen()
-strcharpart({src}, {start} [, {len}]) *strcharpart()*
+strcharpart({src}, {start} [, {len} [, {skipcc}]]) *strcharpart()*
Like |strpart()| but using character index and length instead
- of byte index and length. Composing characters are counted
- separately.
+ of byte index and length.
+ When {skipcc} is omitted or zero, composing characters are
+ counted separately.
+ When {skipcc} set to 1, Composing characters are ignored,
+ similar to |slice()|.
When a character index is used where a character does not
- exist it is assumed to be one character. For example: >
+ exist it is omitted and counted as one character. For
+ example: >
strcharpart('abc', -1, 2)
< results in 'a'.
diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua
index aec5191249..d9c7208c02 100644
--- a/src/nvim/eval.lua
+++ b/src/nvim/eval.lua
@@ -386,7 +386,7 @@ return {
str2list={args={1, 2}, base=1},
str2nr={args={1, 3}, base=1},
strcharlen={args=1, base=1},
- strcharpart={args={2, 3}, base=1, fast=true},
+ strcharpart={args={2, 4}, base=1, fast=true},
strchars={args={1, 2}, base=1},
strdisplaywidth={args={1, 2}, base=1},
strftime={args={1, 2}, base=1},
diff --git a/src/nvim/strings.c b/src/nvim/strings.c
index 61e00f85dc..5231ec0841 100644
--- a/src/nvim/strings.c
+++ b/src/nvim/strings.c
@@ -1834,12 +1834,26 @@ void f_strcharpart(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
const size_t slen = strlen(p);
int nbyte = 0;
+ varnumber_T skipcc = false;
bool error = false;
varnumber_T nchar = tv_get_number_chk(&argvars[1], &error);
if (!error) {
+ if (argvars[2].v_type != VAR_UNKNOWN
+ && argvars[3].v_type != VAR_UNKNOWN) {
+ skipcc = tv_get_bool(&argvars[3]);
+ if (skipcc < 0 || skipcc > 1) {
+ semsg(_(e_using_number_as_bool_nr), skipcc);
+ return;
+ }
+ }
+
if (nchar > 0) {
while (nchar > 0 && (size_t)nbyte < slen) {
- nbyte += utf_ptr2len(p + nbyte);
+ if (skipcc) {
+ nbyte += utfc_ptr2len(p + nbyte);
+ } else {
+ nbyte += utf_ptr2len(p + nbyte);
+ }
nchar--;
}
} else {
@@ -1855,7 +1869,11 @@ void f_strcharpart(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
if (off < 0) {
len += 1;
} else {
- len += utf_ptr2len(p + off);
+ if (skipcc) {
+ len += utfc_ptr2len(p + off);
+ } else {
+ len += utf_ptr2len(p + off);
+ }
}
charlen--;
}
diff --git a/test/old/testdir/test_expr_utf8.vim b/test/old/testdir/test_expr_utf8.vim
index fad725d2e5..c6d2e4ed7e 100644
--- a/test/old/testdir/test_expr_utf8.vim
+++ b/test/old/testdir/test_expr_utf8.vim
@@ -31,4 +31,14 @@ func Test_strcharpart()
call assert_equal('a', strcharpart('àxb', 0, 1))
call assert_equal('̀', strcharpart('àxb', 1, 1))
call assert_equal('x', strcharpart('àxb', 2, 1))
+
+
+ call assert_equal('a', strcharpart('àxb', 0, 1, 0))
+ call assert_equal('à', strcharpart('àxb', 0, 1, 1))
+ call assert_equal('x', strcharpart('àxb', 1, 1, 1))
+
+ call assert_fails("let v = strcharpart('abc', 0, 0, [])", 'E745:')
+ call assert_fails("let v = strcharpart('abc', 0, 0, 2)", 'E1023:')
endfunc
+
+" vim: shiftwidth=2 sts=2 expandtab