]> granicus.if.org Git - vim/commitdiff
patch 8.2.1517: cannot easily get the character under the cursor v8.2.1517
authorBram Moolenaar <Bram@vim.org>
Sun, 23 Aug 2020 15:34:46 +0000 (17:34 +0200)
committerBram Moolenaar <Bram@vim.org>
Sun, 23 Aug 2020 15:34:46 +0000 (17:34 +0200)
Problem:    Cannot easily get the character under the cursor.
Solution:   Add the {chars} argument to strpart().

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

index 370964e567f7d8e4e0ebc9fbfbd3d8fa3e6a4aac..09ef979638e813b044b11ca1304477031976a043 100644 (file)
@@ -2836,7 +2836,8 @@ str2list({expr} [, {utf8}])       List    convert each character of {expr} to
 str2nr({expr} [, {base} [, {quoted}]])
                                Number  convert String to Number
 strcharpart({str}, {start} [, {len}])
-                               String  {len} characters of {str} at {start}
+                               String  {len} characters of {str} at
+                                       character {start}
 strchars({expr} [, {skipcc}])  Number  character length of the String {expr}
 strdisplaywidth({expr} [, {col}]) Number display length of the String {expr}
 strftime({format} [, {time}])  String  format time with a specified format
@@ -2845,8 +2846,9 @@ stridx({haystack}, {needle} [, {start}])
                                Number  index of {needle} in {haystack}
 string({expr})                 String  String representation of {expr} value
 strlen({expr})                 Number  length of the String {expr}
-strpart({str}, {start} [, {len}])
-                               String  {len} bytes of {str} at byte {start}
+strpart({str}, {start} [, {len} [, {chars}]])
+                               String  {len} bytes/chars of {str} at
+                                       byte {start}
 strptime({format}, {timestring})
                                Number  Convert {timestring} to unix timestamp
 strridx({haystack}, {needle} [, {start}])
@@ -3418,7 +3420,8 @@ byte2line({byte})                                 *byte2line()*
 
 byteidx({expr}, {nr})                                  *byteidx()*
                Return byte index of the {nr}'th character in the string
-               {expr}.  Use zero for the first character, it returns zero.
+               {expr}.  Use zero for the first character, it then returns
+               zero.
                This function is only useful when there are multibyte
                characters, otherwise the returned value is equal to {nr}.
                Composing characters are not counted separately, their byte
@@ -9948,17 +9951,22 @@ strlen({expr})  The result is a Number, which is the length of the String
                {expr} in bytes.
                If the argument is a Number it is first converted to a String.
                For other types an error is given.
-               If you want to count the number of multi-byte characters use
+               If you want to count the number of multibyte characters use
                |strchars()|.
                Also see |len()|, |strdisplaywidth()| and |strwidth()|.
 
                Can also be used as a |method|: >
                        GetString()->strlen()
 
-strpart({src}, {start} [, {len}])                      *strpart()*
+strpart({src}, {start} [, {len} [, {chars}]])                  *strpart()*
                The result is a String, which is part of {src}, starting from
                byte {start}, with the byte length {len}.
-               To count characters instead of bytes use |strcharpart()|.
+               When {chars} is present and TRUE then {len} is the number of
+               characters positions (composing characters are not counted
+               separately, thus "1" means one base character and any
+               following composing characters).
+               To count {start} as characters instead of bytes use
+               |strcharpart()|.
 
                When bytes are selected which do not exist, this doesn't
                result in an error, the bytes are simply omitted.
@@ -9970,8 +9978,8 @@ strpart({src}, {start} [, {len}])                 *strpart()*
                        strpart("abcdefg", 3)       == "defg"
 
 <              Note: To get the first character, {start} must be 0.  For
-               example, to get three bytes under and after the cursor: >
-                       strpart(getline("."), col(".") - 1, 3)
+               example, to get the character under the cursor: >
+                       strpart(getline("."), col(".") - 1, 1, v:true)
 <
                Can also be used as a |method|: >
                        GetText()->strpart(5)
index c8747e2c14c2748ebd136220af3d44663b4237a8..fcfd4b10debe747d0722dc2cddac4c9c392d6b06 100644 (file)
@@ -950,7 +950,7 @@ static funcentry_T global_functions[] =
     {"stridx",         2, 3, FEARG_1,    ret_number,   f_stridx},
     {"string",         1, 1, FEARG_1,    ret_string,   f_string},
     {"strlen",         1, 1, FEARG_1,    ret_number,   f_strlen},
-    {"strpart",                2, 3, FEARG_1,    ret_string,   f_strpart},
+    {"strpart",                2, 4, FEARG_1,    ret_string,   f_strpart},
     {"strptime",       2, 2, FEARG_1,    ret_number,
 #ifdef HAVE_STRPTIME
            f_strptime
@@ -8270,10 +8270,8 @@ f_strpart(typval_T *argvars, typval_T *rettv)
     else
        len = slen - n;     // default len: all bytes that are available.
 
-    /*
-     * Only return the overlap between the specified part and the actual
-     * string.
-     */
+    // Only return the overlap between the specified part and the actual
+    // string.
     if (n < 0)
     {
        len += n;
@@ -8286,6 +8284,16 @@ f_strpart(typval_T *argvars, typval_T *rettv)
     else if (n + len > slen)
        len = slen - n;
 
+    if (argvars[2].v_type != VAR_UNKNOWN && argvars[3].v_type != VAR_UNKNOWN)
+    {
+       int off;
+
+       // length in characters
+       for (off = n; off < slen && len > 0; --len)
+           off += mb_ptr2len(p + off);
+       len = off - n;
+    }
+
     rettv->v_type = VAR_STRING;
     rettv->vval.v_string = vim_strnsave(p + n, len);
 }
index dc06bd72ecb878b656dac8ca7f46ea56c0404eb6..e15199b786a219f346825ee7a1f88926786c383e 100644 (file)
@@ -513,6 +513,10 @@ func Test_strpart()
 
   call assert_equal('lép', strpart('éléphant', 2, 4))
   call assert_equal('léphant', strpart('éléphant', 2))
+
+  call assert_equal('é', strpart('éléphant', 0, 1, 1))
+  call assert_equal('ép', strpart('éléphant', 3, 2, v:true))
+  call assert_equal('ó', strpart('cómposed', 1, 1, 1))
 endfunc
 
 func Test_tolower()
index 4c2794af0be5e976f27088e5e79ae231c865aaa4..9eb448b2df0d469dfcf848ffd74814a7bb420101 100644 (file)
@@ -754,6 +754,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1517,
 /**/
     1516,
 /**/