aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/doc/eval.txt7
-rw-r--r--src/nvim/eval.c42
-rw-r--r--src/nvim/po/check.vim88
-rw-r--r--src/nvim/po/cleanup.vim8
-rw-r--r--src/nvim/testdir/test_functions.vim8
5 files changed, 141 insertions, 12 deletions
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index dce531b663..7b5fc191e9 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -2990,11 +2990,16 @@ cosh({expr}) *cosh()*
count({comp}, {expr} [, {ic} [, {start}]]) *count()*
Return the number of times an item with value {expr} appears
- in |List| or |Dictionary| {comp}.
+ in |String|, |List| or |Dictionary| {comp}.
+
If {start} is given then start with the item with this index.
{start} can only be used with a |List|.
+
When {ic} is given and it's |TRUE| then case is ignored.
+ When {comp} is a string then the number of not overlapping
+ occurences of {expr} is returned.
+
*cscope_connection()*
cscope_connection([{num} , {dbpath} [, {prepend}]])
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index 36662b2a39..1ba516a29c 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -7592,9 +7592,38 @@ static void f_copy(typval_T *argvars, typval_T *rettv, FunPtr fptr)
static void f_count(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
long n = 0;
- int ic = FALSE;
+ int ic = 0;
+ bool error = false;
- if (argvars[0].v_type == VAR_LIST) {
+ if (argvars[2].v_type != VAR_UNKNOWN) {
+ ic = tv_get_number_chk(&argvars[2], &error);
+ }
+
+ if (argvars[0].v_type == VAR_STRING) {
+ const char_u *expr = (char_u *)tv_get_string_chk(&argvars[1]);
+ const char_u *p = argvars[0].vval.v_string;
+
+ if (!error && expr != NULL && p != NULL) {
+ if (ic) {
+ const size_t len = STRLEN(expr);
+
+ while (*p != NUL) {
+ if (mb_strnicmp(p, expr, len) == 0) {
+ n++;
+ p += len;
+ } else {
+ MB_PTR_ADV(p);
+ }
+ }
+ } else {
+ char_u *next;
+ while ((next = (char_u *)strstr((char *)p, (char *)expr)) != NULL) {
+ n++;
+ p = next + STRLEN(expr);
+ }
+ }
+ }
+ } else if (argvars[0].v_type == VAR_LIST) {
listitem_T *li;
list_T *l;
long idx;
@@ -7602,9 +7631,6 @@ static void f_count(typval_T *argvars, typval_T *rettv, FunPtr fptr)
if ((l = argvars[0].vval.v_list) != NULL) {
li = tv_list_first(l);
if (argvars[2].v_type != VAR_UNKNOWN) {
- bool error = false;
-
- ic = tv_get_number_chk(&argvars[2], &error);
if (argvars[3].v_type != VAR_UNKNOWN) {
idx = tv_get_number_chk(&argvars[3], &error);
if (!error) {
@@ -7630,10 +7656,7 @@ static void f_count(typval_T *argvars, typval_T *rettv, FunPtr fptr)
hashitem_T *hi;
if ((d = argvars[0].vval.v_dict) != NULL) {
- bool error = false;
-
if (argvars[2].v_type != VAR_UNKNOWN) {
- ic = tv_get_number_chk(&argvars[2], &error);
if (argvars[3].v_type != VAR_UNKNOWN) {
EMSG(_(e_invarg));
}
@@ -7649,8 +7672,9 @@ static void f_count(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
}
- } else
+ } else {
EMSG2(_(e_listdictarg), "count()");
+ }
rettv->vval.v_number = n;
}
diff --git a/src/nvim/po/check.vim b/src/nvim/po/check.vim
index b323174550..eae27ef74d 100644
--- a/src/nvim/po/check.vim
+++ b/src/nvim/po/check.vim
@@ -38,6 +38,7 @@ let s:save_wrapscan = &wrapscan
set nowrapscan
" Start at the first "msgid" line.
+let wsv = winsaveview()
1
/^msgid\>
@@ -113,9 +114,96 @@ if search('msgid "\("\n"\)\?\([EW][0-9]\+:\).*\nmsgstr "\("\n"\)\?[^"]\@=\2\@!')
endif
endif
+func! CountNl(first, last)
+ let nl = 0
+ for lnum in range(a:first, a:last)
+ let nl += count(getline(lnum), "\n")
+ endfor
+ return nl
+endfunc
+
+" Check that the \n at the end of the msgid line is also present in the msgstr
+" line. Skip over the header.
+1
+/^"MIME-Version:
+while 1
+ let lnum = search('^msgid\>')
+ if lnum <= 0
+ break
+ endif
+ let strlnum = search('^msgstr\>')
+ let end = search('^$')
+ if end <= 0
+ let end = line('$') + 1
+ endif
+ let origcount = CountNl(lnum, strlnum - 1)
+ let transcount = CountNl(strlnum, end - 1)
+ " Allow for a few more or less line breaks when there are 2 or more
+ if origcount != transcount && (origcount <= 2 || transcount <= 2)
+ echomsg 'Mismatching "\n" in line ' . line('.')
+ if error == 0
+ let error = lnum
+ endif
+ endif
+endwhile
+
+" Check that the file is well formed according to msgfmts understanding
+if executable("msgfmt")
+ let filename = expand("%")
+ let a = system("msgfmt --statistics OLD_PO_FILE_INPUT=yes " . filename)
+ if v:shell_error != 0
+ let error = matchstr(a, filename.':\zs\d\+\ze:')+0
+ for line in split(a, '\n') | echomsg line | endfor
+ endif
+endif
+
+" Check that the plural form is properly initialized
+1
+let plural = search('^msgid_plural ', 'n')
+if (plural && search('^"Plural-Forms: ', 'n') == 0) || (plural && search('^msgstr\[0\] ".\+"', 'n') != plural + 1)
+ if search('^"Plural-Forms: ', 'n') == 0
+ echomsg "Missing Plural header"
+ if error == 0
+ let error = search('\(^"[A-Za-z-_]\+: .*\\n"\n\)\+\zs', 'n') - 1
+ endif
+ elseif error == 0
+ let error = plural
+ endif
+elseif !plural && search('^"Plural-Forms: ', 'n')
+ " We allow for a stray plural header, msginit adds one.
+endif
+
+" Check that 8bit encoding is used instead of 8-bit
+let cte = search('^"Content-Transfer-Encoding:\s\+8-bit', 'n')
+let ctc = search('^"Content-Type:.*;\s\+\<charset=[iI][sS][oO]_', 'n')
+let ctu = search('^"Content-Type:.*;\s\+\<charset=utf-8', 'n')
+if cte
+ echomsg "Content-Transfer-Encoding should be 8bit instead of 8-bit"
+ " TODO: make this an error
+ " if error == 0
+ " let error = cte
+ " endif
+elseif ctc
+ echomsg "Content-Type charset should be 'ISO-...' instead of 'ISO_...'"
+ " TODO: make this an error
+ " if error == 0
+ " let error = ct
+ " endif
+elseif ctu
+ echomsg "Content-Type charset should be 'UTF-8' instead of 'utf-8'"
+ " TODO: make this an error
+ " if error == 0
+ " let error = ct
+ " endif
+endif
+
+
if error == 0
+ " If all was OK restore the view.
+ call winrestview(wsv)
echomsg "OK"
else
+ " Put the cursor on the line with the error.
exe error
endif
diff --git a/src/nvim/po/cleanup.vim b/src/nvim/po/cleanup.vim
index 24ae74ed38..b27d88092f 100644
--- a/src/nvim/po/cleanup.vim
+++ b/src/nvim/po/cleanup.vim
@@ -8,12 +8,18 @@
let s:was_diff = &diff
setl nodiff
-silent g/^#: /d
+" untranslated message preceded by c-format or comment
+silent g/^#, c-format\n#/.d
+silent g/^#\..*\n#/.d
+
+silent g/^#[:~] /d
silent g/^#, fuzzy\(, .*\)\=\nmsgid ""\@!/.+1,/^$/-1s/^/#\~ /
silent g/^msgstr"/s//msgstr "/
silent g/^msgid"/s//msgid "/
silent g/^msgstr ""\(\n"\)\@!/?^msgid?,.s/^/#\~ /
+silent g/^\n\n\n/.d
+
if s:was_diff
setl diff
endif
diff --git a/src/nvim/testdir/test_functions.vim b/src/nvim/testdir/test_functions.vim
index c59134908c..3b16f2ce9f 100644
--- a/src/nvim/testdir/test_functions.vim
+++ b/src/nvim/testdir/test_functions.vim
@@ -680,7 +680,13 @@ func Test_count()
call assert_equal(0, count(d, 'c', 1))
call assert_fails('call count(d, "a", 0, 1)', 'E474:')
- call assert_fails('call count("a", "a")', 'E712:')
+
+ call assert_equal(0, count("foo", "bar"))
+ call assert_equal(1, count("foo", "oo"))
+ call assert_equal(2, count("foo", "o"))
+ call assert_equal(0, count("foo", "O"))
+ call assert_equal(2, count("foo", "O", 1))
+ call assert_equal(2, count("fooooo", "oo"))
endfunc
func Test_changenr()