Skip to content

Commit 6c53fca

Browse files
committed
patch 8.2.1517: cannot easily get the character under the cursor
Problem: Cannot easily get the character under the cursor. Solution: Add the {chars} argument to strpart().
1 parent 430deb1 commit 6c53fca

4 files changed

Lines changed: 36 additions & 14 deletions

File tree

runtime/doc/eval.txt

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2836,7 +2836,8 @@ str2list({expr} [, {utf8}]) List convert each character of {expr} to
28362836
str2nr({expr} [, {base} [, {quoted}]])
28372837
Number convert String to Number
28382838
strcharpart({str}, {start} [, {len}])
2839-
String {len} characters of {str} at {start}
2839+
String {len} characters of {str} at
2840+
character {start}
28402841
strchars({expr} [, {skipcc}]) Number character length of the String {expr}
28412842
strdisplaywidth({expr} [, {col}]) Number display length of the String {expr}
28422843
strftime({format} [, {time}]) String format time with a specified format
@@ -2845,8 +2846,9 @@ stridx({haystack}, {needle} [, {start}])
28452846
Number index of {needle} in {haystack}
28462847
string({expr}) String String representation of {expr} value
28472848
strlen({expr}) Number length of the String {expr}
2848-
strpart({str}, {start} [, {len}])
2849-
String {len} bytes of {str} at byte {start}
2849+
strpart({str}, {start} [, {len} [, {chars}]])
2850+
String {len} bytes/chars of {str} at
2851+
byte {start}
28502852
strptime({format}, {timestring})
28512853
Number Convert {timestring} to unix timestamp
28522854
strridx({haystack}, {needle} [, {start}])
@@ -3418,7 +3420,8 @@ byte2line({byte}) *byte2line()*
34183420

34193421
byteidx({expr}, {nr}) *byteidx()*
34203422
Return byte index of the {nr}'th character in the string
3421-
{expr}. Use zero for the first character, it returns zero.
3423+
{expr}. Use zero for the first character, it then returns
3424+
zero.
34223425
This function is only useful when there are multibyte
34233426
characters, otherwise the returned value is equal to {nr}.
34243427
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
99489951
{expr} in bytes.
99499952
If the argument is a Number it is first converted to a String.
99509953
For other types an error is given.
9951-
If you want to count the number of multi-byte characters use
9954+
If you want to count the number of multibyte characters use
99529955
|strchars()|.
99539956
Also see |len()|, |strdisplaywidth()| and |strwidth()|.
99549957

99559958
Can also be used as a |method|: >
99569959
GetString()->strlen()
99579960

9958-
strpart({src}, {start} [, {len}]) *strpart()*
9961+
strpart({src}, {start} [, {len} [, {chars}]]) *strpart()*
99599962
The result is a String, which is part of {src}, starting from
99609963
byte {start}, with the byte length {len}.
9961-
To count characters instead of bytes use |strcharpart()|.
9964+
When {chars} is present and TRUE then {len} is the number of
9965+
characters positions (composing characters are not counted
9966+
separately, thus "1" means one base character and any
9967+
following composing characters).
9968+
To count {start} as characters instead of bytes use
9969+
|strcharpart()|.
99629970

99639971
When bytes are selected which do not exist, this doesn't
99649972
result in an error, the bytes are simply omitted.
@@ -9970,8 +9978,8 @@ strpart({src}, {start} [, {len}]) *strpart()*
99709978
strpart("abcdefg", 3) == "defg"
99719979

99729980
< Note: To get the first character, {start} must be 0. For
9973-
example, to get three bytes under and after the cursor: >
9974-
strpart(getline("."), col(".") - 1, 3)
9981+
example, to get the character under the cursor: >
9982+
strpart(getline("."), col(".") - 1, 1, v:true)
99759983
<
99769984
Can also be used as a |method|: >
99779985
GetText()->strpart(5)

src/evalfunc.c

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -950,7 +950,7 @@ static funcentry_T global_functions[] =
950950
{"stridx", 2, 3, FEARG_1, ret_number, f_stridx},
951951
{"string", 1, 1, FEARG_1, ret_string, f_string},
952952
{"strlen", 1, 1, FEARG_1, ret_number, f_strlen},
953-
{"strpart", 2, 3, FEARG_1, ret_string, f_strpart},
953+
{"strpart", 2, 4, FEARG_1, ret_string, f_strpart},
954954
{"strptime", 2, 2, FEARG_1, ret_number,
955955
#ifdef HAVE_STRPTIME
956956
f_strptime
@@ -8270,10 +8270,8 @@ f_strpart(typval_T *argvars, typval_T *rettv)
82708270
else
82718271
len = slen - n; // default len: all bytes that are available.
82728272

8273-
/*
8274-
* Only return the overlap between the specified part and the actual
8275-
* string.
8276-
*/
8273+
// Only return the overlap between the specified part and the actual
8274+
// string.
82778275
if (n < 0)
82788276
{
82798277
len += n;
@@ -8286,6 +8284,16 @@ f_strpart(typval_T *argvars, typval_T *rettv)
82868284
else if (n + len > slen)
82878285
len = slen - n;
82888286

8287+
if (argvars[2].v_type != VAR_UNKNOWN && argvars[3].v_type != VAR_UNKNOWN)
8288+
{
8289+
int off;
8290+
8291+
// length in characters
8292+
for (off = n; off < slen && len > 0; --len)
8293+
off += mb_ptr2len(p + off);
8294+
len = off - n;
8295+
}
8296+
82898297
rettv->v_type = VAR_STRING;
82908298
rettv->vval.v_string = vim_strnsave(p + n, len);
82918299
}

src/testdir/test_functions.vim

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,10 @@ func Test_strpart()
513513

514514
call assert_equal('lép', strpart('éléphant', 2, 4))
515515
call assert_equal('léphant', strpart('éléphant', 2))
516+
517+
call assert_equal('é', strpart('éléphant', 0, 1, 1))
518+
call assert_equal('ép', strpart('éléphant', 3, 2, v:true))
519+
call assert_equal('', strpart('cómposed', 1, 1, 1))
516520
endfunc
517521

518522
func Test_tolower()

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -754,6 +754,8 @@ static char *(features[]) =
754754

755755
static int included_patches[] =
756756
{ /* Add new patch number below this line */
757+
/**/
758+
1517,
757759
/**/
758760
1516,
759761
/**/

0 commit comments

Comments
 (0)