]> granicus.if.org Git - vim/commitdiff
patch 8.2.2606: strchars() defaults to counting composing characters v8.2.2606
authorBram Moolenaar <Bram@vim.org>
Sun, 14 Mar 2021 18:02:09 +0000 (19:02 +0100)
committerBram Moolenaar <Bram@vim.org>
Sun, 14 Mar 2021 18:02:09 +0000 (19:02 +0100)
Problem:    strchars() defaults to counting composing characters.
Solution:   Add strcharlen() which ignores composing characters.

runtime/doc/eval.txt
runtime/doc/usr_41.txt
src/evalfunc.c
src/testdir/test_utf8.vim
src/version.c

index 92f020689e71236a38a1d96999d97b6b49117b13..3e5c6ee44b1ec3da219c4b95bda5ba94503ae52c 100644 (file)
@@ -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
index 8113bef8e54840569a1ebfacd0d6db83f1c88ded..0d17298fb03494d245d53864e751f9b6962dd549 100644 (file)
@@ -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
index 29bbe8ab879afab04b9b275e1f9fb160ad9026f7..34369d77add16bfa76490512c0bbc4bfbdc2c97e 100644 (file)
@@ -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);
 }
 
 /*
index a5fd4fb89a3e5935bab84abf2043b90164307d89..5454e430ad084c44b93ead2dbc9af165d9341535 100644 (file)
@@ -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
index c5797c32b9a7a3432bab29fc0b8250d020deec9e..918a34c98f2445e60fdf44c725d8814fff7d61c5 100644 (file)
@@ -750,6 +750,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    2606,
 /**/
     2605,
 /**/