diff options
author | zeertzjq <zeertzjq@outlook.com> | 2023-05-04 17:42:34 +0800 |
---|---|---|
committer | zeertzjq <zeertzjq@outlook.com> | 2023-05-04 17:49:56 +0800 |
commit | 3724e65c30f7d1ef803ac4e34eab7d4a9531b1a8 (patch) | |
tree | 6ddfb2294ae444c18f81f670500ea3f0f6fb5d88 | |
parent | b441dafdf53e367c7d43177274bd781c5c73e6e0 (diff) | |
download | rneovim-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.txt | 15 | ||||
-rw-r--r-- | src/nvim/eval.lua | 2 | ||||
-rw-r--r-- | src/nvim/strings.c | 22 | ||||
-rw-r--r-- | test/old/testdir/test_expr_utf8.vim | 10 |
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 |