Hi Bram and list,
I want to get the number of characters.
strchars() is looks best, but composing characters are counted separately.
So that I add "skip composing characters flag" to strchars().
strchars({expr} [, {skipcc}]) strchars()
The result is a Number, which is the number of characters
String {expr} occupies.
When {skipcc} is omitted or zero, Composing characters are
counted separately.
When {skipcc} set to 1, Composing characters are skipped.
Also see strlen(), strdisplaywidth() and strwidth().
Of course I know we can get the number of characters below.
:let len = strlen(substitute(str, ".", "x", "g"))
But it is not intuitive :-)
Can you include this patch?
PS
This patch idea by Ken Takata. and many advice by Ken Takata.
Thanks
--
Best regards,
Hirohito Higashi (a.k.a h_east)
--
--
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].
For more options, visit https://groups.google.com/d/optout.
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -1985,7 +1985,7 @@
sqrt( {expr}) Float square root of {expr}
str2float( {expr}) Float convert String to Float
str2nr( {expr} [, {base}]) Number convert String to Number
-strchars( {expr}) Number character length of the String {expr}
+strchars( {expr} [, {skipcc}]) Number character length of the String {expr}
strdisplaywidth( {expr} [, {col}]) Number display length of the String {expr}
strftime( {format}[, {time}]) String time in specified format
stridx( {haystack}, {needle}[, {start}])
@@ -5839,10 +5839,12 @@
Text after the number is silently ignored.
-strchars({expr}) *strchars()*
+strchars({expr} [, {skipcc}]) *strchars()*
The result is a Number, which is the number of characters
- String {expr} occupies. Composing characters are counted
- separately.
+ String {expr} occupies.
+ When {skipcc} is omitted or zero, Composing characters are
+ counted separately.
+ When {skipcc} set to 1, Composing characters are skipped.
Also see |strlen()|, |strdisplaywidth()| and |strwidth()|.
strdisplaywidth({expr}[, {col}]) *strdisplaywidth()*
@@ -5916,6 +5918,8 @@
If you want to count the number of multi-byte characters (not
counting composing characters) use something like this: >
+ :let len = strchars(str, 1)
+< Or: >
:let len = strlen(substitute(str, ".", "x", "g"))
<
If the argument is a Number it is first converted to a String.
diff --git a/src/eval.c b/src/eval.c
--- a/src/eval.c
+++ b/src/eval.c
@@ -8309,7 +8309,7 @@
{"str2float", 1, 1, f_str2float},
#endif
{"str2nr", 1, 2, f_str2nr},
- {"strchars", 1, 1, f_strchars},
+ {"strchars", 1, 2, f_strchars},
{"strdisplaywidth", 1, 2, f_strdisplaywidth},
#ifdef HAVE_STRFTIME
{"strftime", 1, 2, f_strftime},
@@ -18372,18 +18372,30 @@
typval_T *rettv;
{
char_u *s = get_tv_string(&argvars[0]);
+ int skipcc = 0;
#ifdef FEAT_MBYTE
varnumber_T len = 0;
-
- while (*s != NUL)
- {
- mb_cptr2char_adv(&s);
- ++len;
- }
- rettv->vval.v_number = len;
+ int (*func_mb_ptr2char_adv)(char_u **pp);
+#endif
+
+ if (argvars[1].v_type != VAR_UNKNOWN)
+ skipcc = get_tv_number_chk(&argvars[1], NULL);
+ if (skipcc < 0 || skipcc > 1)
+ EMSG(_(e_invarg));
+ else
+ {
+#ifdef FEAT_MBYTE
+ 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;
#else
- rettv->vval.v_number = (varnumber_T)(STRLEN(s));
-#endif
+ rettv->vval.v_number = (varnumber_T)(STRLEN(s));
+#endif
+ }
}
/*
diff --git a/src/testdir/test_utf8.in b/src/testdir/test_utf8.in
--- a/src/testdir/test_utf8.in
+++ b/src/testdir/test_utf8.in
@@ -11,6 +11,12 @@
:
:bwipeout!
:$put=r
+:" Test for built-in function strchars()
+:for str in ["a", "あいa", "A\u20dd", "A\u20dd\u20dd", "\u20dd"]
+: $put=strchars(str)
+: $put=strchars(str, 0)
+: $put=strchars(str, 1)
+:endfor
:call garbagecollect(1)
:/^start:/,$wq! test.out
ENDTEST
diff --git a/src/testdir/test_utf8.ok b/src/testdir/test_utf8.ok
--- a/src/testdir/test_utf8.ok
+++ b/src/testdir/test_utf8.ok
@@ -2,3 +2,18 @@
axaa
xあああ
bxbb
+1
+1
+1
+3
+3
+3
+2
+2
+1
+3
+3
+1
+1
+1
+1