Patch 8.2.2233
Problem:    Cannot convert a byte index into a character index.
Solution:   Add charidx(). (Yegappan Lakshmanan, closes #7561)
Files:      runtime/doc/eval.txt, runtime/doc/usr_41.txt, src/evalfunc.c,
            src/testdir/test_functions.vim


*** ../vim-8.2.2232/runtime/doc/eval.txt        2020-11-30 17:40:41.299714396 
+0100
--- runtime/doc/eval.txt        2020-12-28 12:55:01.155827080 +0100
***************
*** 2441,2446 ****
--- 2475,2482 ----
  changenr()                    Number  current change number
  char2nr({expr} [, {utf8}])    Number  ASCII/UTF8 value of first char in {expr}
  charclass({string})           Number  character class of {string}
+ charidx({string}, {idx} [, {countcc}])
+                               Number  char index of byte {idx} in {string}
  chdir({dir})                  String  change current working directory
  cindent({lnum})                       Number  C indent for line {lnum}
  clearmatches([{win}])         none    clear all matches
***************
*** 3550,3555 ****
--- 3590,3620 ----
                        other   specific Unicode class
                The class is used in patterns and word motions.
  
+                                                       *charidx()*
+ charidx({string}, {idx} [, {countcc}])
+               Return the character index of the byte at {idx} in {string}.
+               The index of the first character is zero.
+               If there are no multibyte characters the returned value is
+               equal to {idx}.
+               When {countcc} is omitted or zero, then composing characters
+               are not counted separately, their byte length is added to the
+               preceding base character.
+               When {countcc} is set to 1, then composing characters are
+               counted as separate characters.
+               Returns -1 if the arguments are invalid or if {idx} is greater
+               than the index of the last byte in {string}.  An error is
+               given if the first argument is not a string, the second
+               argument is not a number or when the third argument is present
+               and is not zero or one.
+               See |byteidx()| and |byteidxcomp()| for getting the byte index
+               from the character index.
+               Examples: >
+                       echo charidx('áb́ć', 3)               returns 1
+                       echo charidx('áb́ć', 6, 1)    returns 4
+                       echo charidx('áb́ć', 16)              returns -1
+ <
+               Can also be used as a |method|: >
+                       GetName()->charidx(idx)
  
  chdir({dir})                                          *chdir()*
                Change the current working directory to {dir}.  The scope of
*** ../vim-8.2.2232/runtime/doc/usr_41.txt      2020-11-09 18:31:30.544791868 
+0100
--- runtime/doc/usr_41.txt      2020-12-28 12:47:17.340500809 +0100
***************
*** 617,622 ****
--- 625,631 ----
        iconv()                 convert text from one encoding to another
        byteidx()               byte index of a character in a string
        byteidxcomp()           like byteidx() but count composing characters
+       charidx()               character index of a byte in a string
        repeat()                repeat a string multiple times
        eval()                  evaluate a string expression
        execute()               execute an Ex command and get the output
*** ../vim-8.2.2232/src/evalfunc.c      2020-12-21 21:58:42.607687803 +0100
--- src/evalfunc.c      2020-12-28 12:51:40.224101632 +0100
***************
*** 47,52 ****
--- 47,53 ----
  #endif
  static void f_changenr(typval_T *argvars, typval_T *rettv);
  static void f_char2nr(typval_T *argvars, typval_T *rettv);
+ static void f_charidx(typval_T *argvars, typval_T *rettv);
  static void f_col(typval_T *argvars, typval_T *rettv);
  static void f_confirm(typval_T *argvars, typval_T *rettv);
  static void f_copy(typval_T *argvars, typval_T *rettv);
***************
*** 789,794 ****
--- 790,797 ----
                        ret_number,         f_char2nr},
      {"charclass",     1, 1, FEARG_1,      NULL,
                        ret_number,         f_charclass},
+     {"charidx",               2, 3, FEARG_1,      NULL,
+                       ret_number,         f_charidx},
      {"chdir",         1, 1, FEARG_1,      NULL,
                        ret_string,         f_chdir},
      {"cindent",               1, 1, FEARG_1,      NULL,
***************
*** 2420,2425 ****
--- 2423,2479 ----
        rettv->vval.v_number = tv_get_string(&argvars[0])[0];
  }
  
+ /*
+  * "charidx()" function
+  */
+     static void
+ f_charidx(typval_T *argvars, typval_T *rettv)
+ {
+     char_u    *str;
+     varnumber_T       idx;
+     int               countcc = FALSE;
+     char_u    *p;
+     int               len;
+     int               (*ptr2len)(char_u *);
+ 
+     rettv->vval.v_number = -1;
+ 
+     if (argvars[0].v_type != VAR_STRING || argvars[1].v_type != VAR_NUMBER
+           || (argvars[2].v_type != VAR_UNKNOWN
+                                          && argvars[2].v_type != VAR_NUMBER))
+     {
+       emsg(_(e_invarg));
+       return;
+     }
+ 
+     str = tv_get_string_chk(&argvars[0]);
+     idx = tv_get_number_chk(&argvars[1], NULL);
+     if (str == NULL || idx < 0)
+       return;
+ 
+     if (argvars[2].v_type != VAR_UNKNOWN)
+       countcc = (int)tv_get_bool(&argvars[2]);
+     if (countcc < 0 || countcc > 1)
+     {
+       semsg(_(e_using_number_as_bool_nr), countcc);
+       return;
+     }
+ 
+     if (enc_utf8 && countcc)
+       ptr2len = utf_ptr2len;
+     else
+       ptr2len = mb_ptr2len;
+ 
+     for (p = str, len = 0; p <= str + idx; len++)
+     {
+       if (*p == NUL)
+           return;
+       p += ptr2len(p);
+     }
+ 
+     rettv->vval.v_number = len > 0 ? len - 1 : 0;
+ }
+ 
      win_T *
  get_optional_window(typval_T *argvars, int idx)
  {
*** ../vim-8.2.2232/src/testdir/test_functions.vim      2020-12-06 
15:03:14.821379868 +0100
--- src/testdir/test_functions.vim      2020-12-28 12:47:17.340500809 +0100
***************
*** 1132,1137 ****
--- 1132,1162 ----
    call assert_fails("call byteidxcomp([], 0)", 'E730:')
  endfunc
  
+ " Test for charidx()
+ func Test_charidx()
+   let a = 'xáb́y'
+   call assert_equal(0, charidx(a, 0))
+   call assert_equal(1, charidx(a, 3))
+   call assert_equal(2, charidx(a, 4))
+   call assert_equal(3, charidx(a, 7))
+   call assert_equal(-1, charidx(a, 8))
+   call assert_equal(-1, charidx('', 0))
+ 
+   " count composing characters
+   call assert_equal(0, charidx(a, 0, 1))
+   call assert_equal(2, charidx(a, 2, 1))
+   call assert_equal(3, charidx(a, 4, 1))
+   call assert_equal(5, charidx(a, 7, 1))
+   call assert_equal(-1, charidx(a, 8, 1))
+   call assert_equal(-1, charidx('', 0, 1))
+ 
+   call assert_fails('let x = charidx([], 1)', 'E474:')
+   call assert_fails('let x = charidx("abc", [])', 'E474:')
+   call assert_fails('let x = charidx("abc", 1, [])', 'E474:')
+   call assert_fails('let x = charidx("abc", 1, -1)', 'E1023:')
+   call assert_fails('let x = charidx("abc", 1, 2)', 'E1023:')
+ endfunc
+ 
  func Test_count()
    let l = ['a', 'a', 'A', 'b']
    call assert_equal(2, count(l, 'a'))
*** ../vim-8.2.2232/src/version.c       2020-12-27 19:17:52.507402031 +0100
--- src/version.c       2020-12-28 12:55:51.975736909 +0100
***************
*** 752,753 ****
--- 752,755 ----
  {   /* Add new patch number below this line */
+ /**/
+     2233,
  /**/

-- 
To define recursion, we must first define recursion.

 /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net   \\\
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\  an exciting new programming language -- http://www.Zimbu.org        ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/202012281157.0BSBvQ4J262332%40masaka.moolenaar.net.

Raspunde prin e-mail lui