diff options
author | Bram Moolenaar <Bram@vim.org> | 2021-03-14 19:02:09 +0100 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2021-03-14 19:02:09 +0100 |
commit | 70ce8a1561c5396e4c4381f76a005cbb97646f80 (patch) | |
tree | ed4c9ae3c5e62d9f2880fb01c267ada1df76bff0 | |
parent | 0289a093a4d65c6280a3be118d1d3696d1aa74da (diff) | |
download | vim-git-70ce8a1561c5396e4c4381f76a005cbb97646f80.tar.gz |
patch 8.2.2606: strchars() defaults to counting composing charactersv8.2.2606
Problem: strchars() defaults to counting composing characters.
Solution: Add strcharlen() which ignores composing characters.
-rw-r--r-- | runtime/doc/eval.txt | 19 | ||||
-rw-r--r-- | runtime/doc/usr_41.txt | 3 | ||||
-rw-r--r-- | src/evalfunc.c | 41 | ||||
-rw-r--r-- | src/testdir/test_utf8.vim | 9 | ||||
-rw-r--r-- | src/version.c | 2 |
5 files changed, 59 insertions, 15 deletions
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index 92f020689..3e5c6ee44 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -2923,10 +2923,11 @@ str2list({expr} [, {utf8}]) List convert each character of {expr} to ASCII/UTF8 value str2nr({expr} [, {base} [, {quoted}]]) Number convert String to Number +strcharlen({expr}) Number character length of the String {expr} strcharpart({str}, {start} [, {len}]) String {len} characters of {str} at character {start} -strchars({expr} [, {skipcc}]) Number character length of the String {expr} +strchars({expr} [, {skipcc}]) Number character count of the String {expr} strdisplaywidth({expr} [, {col}]) Number display length of the String {expr} strftime({format} [, {time}]) String format time with a specified format strgetchar({str}, {index}) Number get char {index} from {str} @@ -10276,6 +10277,19 @@ str2nr({expr} [, {base} [, {quoted}]]) *str2nr()* Can also be used as a |method|: > GetText()->str2nr() + +strcharlen({expr}) *strcharlen()* + The result is a Number, which is the number of characters + in String {expr}. Composing characters are ignored. + |strchars()| can count the number of characters, counting + composing characters separately. + + Also see |strlen()|, |strdisplaywidth()| and |strwidth()|. + + Can also be used as a |method|: > + GetText()->strcharlen() + + strcharpart({src}, {start} [, {len}]) *strcharpart()* Like |strpart()| but using character index and length instead of byte index and length. Composing characters are counted @@ -10288,12 +10302,15 @@ strcharpart({src}, {start} [, {len}]) *strcharpart()* Can also be used as a |method|: > GetText()->strcharpart(5) + strchars({expr} [, {skipcc}]) *strchars()* The result is a Number, which is the number of characters in String {expr}. When {skipcc} is omitted or zero, composing characters are counted separately. When {skipcc} set to 1, Composing characters are ignored. + |strcharlen()| does the same. + Also see |strlen()|, |strdisplaywidth()| and |strwidth()|. {skipcc} is only available after 7.4.755. For backward diff --git a/runtime/doc/usr_41.txt b/runtime/doc/usr_41.txt index 8113bef8e..0d17298fb 100644 --- a/runtime/doc/usr_41.txt +++ b/runtime/doc/usr_41.txt @@ -611,7 +611,8 @@ String manipulation: *string-functions* stridx() first index of a short string in a long string strridx() last index of a short string in a long string strlen() length of a string in bytes - strchars() length of a string in characters + strcharlen() length of a string in characters + strchars() number of characters in a string strwidth() size of string when displayed strdisplaywidth() size of string when displayed, deals with tabs setcellwidths() set character cell width overrides diff --git a/src/evalfunc.c b/src/evalfunc.c index 29bbe8ab8..34369d77a 100644 --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -223,6 +223,7 @@ static void f_str2float(typval_T *argvars, typval_T *rettv); #endif static void f_str2list(typval_T *argvars, typval_T *rettv); static void f_str2nr(typval_T *argvars, typval_T *rettv); +static void f_strcharlen(typval_T *argvars, typval_T *rettv); static void f_strchars(typval_T *argvars, typval_T *rettv); static void f_strgetchar(typval_T *argvars, typval_T *rettv); static void f_stridx(typval_T *argvars, typval_T *rettv); @@ -1572,6 +1573,8 @@ static funcentry_T global_functions[] = ret_list_number, f_str2list}, {"str2nr", 1, 3, FEARG_1, arg3_string_nr_bool, ret_number, f_str2nr}, + {"strcharlen", 1, 1, FEARG_1, NULL, + ret_number, f_strcharlen}, {"strcharpart", 2, 3, FEARG_1, NULL, ret_string, f_strcharpart}, {"strchars", 1, 2, FEARG_1, NULL, @@ -9236,31 +9239,45 @@ f_strlen(typval_T *argvars, typval_T *rettv) tv_get_string(&argvars[0]))); } + static void +strchar_common(typval_T *argvars, typval_T *rettv, int skipcc) +{ + char_u *s = tv_get_string(&argvars[0]); + varnumber_T len = 0; + int (*func_mb_ptr2char_adv)(char_u **pp); + + func_mb_ptr2char_adv = skipcc ? mb_ptr2char_adv : mb_cptr2char_adv; + while (*s != NUL) + { + func_mb_ptr2char_adv(&s); + ++len; + } + rettv->vval.v_number = len; +} + +/* + * "strcharlen()" function + */ + static void +f_strcharlen(typval_T *argvars, typval_T *rettv) +{ + strchar_common(argvars, rettv, TRUE); +} + /* * "strchars()" function */ static void f_strchars(typval_T *argvars, typval_T *rettv) { - char_u *s = tv_get_string(&argvars[0]); varnumber_T skipcc = FALSE; - varnumber_T len = 0; - int (*func_mb_ptr2char_adv)(char_u **pp); if (argvars[1].v_type != VAR_UNKNOWN) skipcc = tv_get_bool(&argvars[1]); if (skipcc < 0 || skipcc > 1) semsg(_(e_using_number_as_bool_nr), skipcc); else - { - func_mb_ptr2char_adv = skipcc ? mb_ptr2char_adv : mb_cptr2char_adv; - while (*s != NUL) - { - func_mb_ptr2char_adv(&s); - ++len; - } - rettv->vval.v_number = len; - } + strchar_common(argvars, rettv, skipcc); } /* diff --git a/src/testdir/test_utf8.vim b/src/testdir/test_utf8.vim index a5fd4fb89..5454e430a 100644 --- a/src/testdir/test_utf8.vim +++ b/src/testdir/test_utf8.vim @@ -11,7 +11,7 @@ func Test_visual_block_insert() bwipeout! endfunc -" Test for built-in function strchars() +" Test for built-in functions strchars() and strcharlen() func Test_strchars() let inp = ["a", "あいa", "A\u20dd", "A\u20dd\u20dd", "\u20dd"] let exp = [[1, 1, 1], [3, 3, 3], [2, 2, 1], [3, 3, 1], [1, 1, 1]] @@ -20,6 +20,13 @@ func Test_strchars() call assert_equal(exp[i][1], inp[i]->strchars(0)) call assert_equal(exp[i][2], strchars(inp[i], 1)) endfor + + let exp = [1, 3, 1, 1, 1] + for i in range(len(inp)) + call assert_equal(exp[i], inp[i]->strcharlen()) + call assert_equal(exp[i], strcharlen(inp[i])) + endfor + call assert_fails("let v=strchars('abc', [])", 'E745:') call assert_fails("let v=strchars('abc', 2)", 'E1023:') endfunc diff --git a/src/version.c b/src/version.c index c5797c32b..918a34c98 100644 --- a/src/version.c +++ b/src/version.c @@ -751,6 +751,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 2606, +/**/ 2605, /**/ 2604, |