summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2017-03-08 22:19:26 +0100
committerBram Moolenaar <Bram@vim.org>2017-03-08 22:19:26 +0100
commit7720ba8599162fbbb8f7fc034f674a2ccd3ca7f1 (patch)
treed130bb2242a5993528be171cee687af290525a53
parentbb962262eb6b18d93161d7506317d215ae80bfe5 (diff)
patch 8.0.0431: 'cinoptions' cannot set indent for extern blockv8.0.0431
Problem: 'cinoptions' cannot set indent for extern block. Solution: Add the "E" flag in 'cinoptions'. (Hirohito Higashi)
-rw-r--r--runtime/doc/indent.txt17
-rw-r--r--src/misc1.c68
-rw-r--r--src/structs.h1
-rw-r--r--src/testdir/test_cindent.vim60
-rw-r--r--src/version.c2
5 files changed, 145 insertions, 3 deletions
diff --git a/runtime/doc/indent.txt b/runtime/doc/indent.txt
index fdb7c67edb..efb0a7d792 100644
--- a/runtime/doc/indent.txt
+++ b/runtime/doc/indent.txt
@@ -325,6 +325,21 @@ The examples below assume a 'shiftwidth' of 4.
void function(); void function();
} }
<
+ *cino-E*
+ EN Indent inside C++ linkage specifications (extern "C" or
+ extern "C++") N characters extra compared to a normal block.
+ (default 0).
+
+ cino= cino=E-s >
+ extern "C" { extern "C" {
+ void function(); void function();
+ } }
+
+ extern "C" extern "C"
+ { {
+ void function(); void function();
+ } }
+<
*cino-p*
pN Parameter declarations for K&R-style function declarations will
be indented N characters from the margin. (default
@@ -554,7 +569,7 @@ The examples below assume a 'shiftwidth' of 4.
The defaults, spelled out in full, are:
- cinoptions=>s,e0,n0,f0,{0,}0,^0,L-1,:s,=s,l0,b0,gs,hs,N0,ps,ts,is,+s,
+ cinoptions=>s,e0,n0,f0,{0,}0,^0,L-1,:s,=s,l0,b0,gs,hs,N0,E0,ps,ts,is,+s,
c3,C0,/0,(2s,us,U0,w0,W0,k0,m0,j0,J0,)20,*70,#0
Vim puts a line in column 1 if:
diff --git a/src/misc1.c b/src/misc1.c
index ec92f03757..c6b8d13b78 100644
--- a/src/misc1.c
+++ b/src/misc1.c
@@ -5810,6 +5810,54 @@ cin_is_cpp_namespace(char_u *s)
}
/*
+ * Recognize a `extern "C"` or `extern "C++"` linkage specifications.
+ */
+ static int
+cin_is_cpp_extern_c(char_u *s)
+{
+ char_u *p;
+ int has_string_literal = FALSE;
+
+ s = cin_skipcomment(s);
+ if (STRNCMP(s, "extern", 6) == 0 && (s[6] == NUL || !vim_iswordc(s[6])))
+ {
+ p = cin_skipcomment(skipwhite(s + 6));
+ while (*p != NUL)
+ {
+ if (vim_iswhite(*p))
+ {
+ p = cin_skipcomment(skipwhite(p));
+ }
+ else if (*p == '{')
+ {
+ break;
+ }
+ else if (p[0] == '"' && p[1] == 'C' && p[2] == '"')
+ {
+ if (has_string_literal)
+ return FALSE;
+ has_string_literal = TRUE;
+ p += 3;
+ }
+ else if (p[0] == '"' && p[1] == 'C' && p[2] == '+' && p[3] == '+'
+ && p[4] == '"')
+ {
+ if (has_string_literal)
+ return FALSE;
+ has_string_literal = TRUE;
+ p += 5;
+ }
+ else
+ {
+ return FALSE;
+ }
+ }
+ return has_string_literal ? TRUE : FALSE;
+ }
+ return FALSE;
+}
+
+/*
* Return a pointer to the first non-empty non-comment character after a ':'.
* Return NULL if not found.
* case 234: a = b;
@@ -6652,6 +6700,7 @@ cin_skip2pos(pos_T *trypos)
{
char_u *line;
char_u *p;
+ char_u *new_p;
p = line = ml_get(trypos->lnum);
while (*p && (colnr_T)(p - line) < trypos->col)
@@ -6660,8 +6709,11 @@ cin_skip2pos(pos_T *trypos)
p = cin_skipcomment(p);
else
{
- p = skip_string(p);
- ++p;
+ new_p = skip_string(p);
+ if (new_p == p)
+ ++p;
+ else
+ p = new_p;
}
}
return (int)(p - line);
@@ -6977,6 +7029,9 @@ parse_cino(buf_T *buf)
/* indentation for # comments */
buf->b_ind_hash_comment = 0;
+ /* Handle C++ extern "C" or "C++" */
+ buf->b_ind_cpp_extern_c = 0;
+
for (p = buf->b_p_cino; *p; )
{
l = p++;
@@ -7051,6 +7106,7 @@ parse_cino(buf_T *buf)
case '#': buf->b_ind_hash_comment = n; break;
case 'N': buf->b_ind_cpp_namespace = n; break;
case 'k': buf->b_ind_if_for_while = n; break;
+ case 'E': buf->b_ind_cpp_extern_c = n; break;
}
if (*p == ',')
++p;
@@ -7764,6 +7820,8 @@ get_c_indent(void)
l = skipwhite(ml_get_curline());
if (cin_is_cpp_namespace(l))
amount += curbuf->b_ind_cpp_namespace;
+ else if (cin_is_cpp_extern_c(l))
+ amount += curbuf->b_ind_cpp_extern_c;
}
else
{
@@ -7990,6 +8048,12 @@ get_c_indent(void)
- added_to_amount;
break;
}
+ else if (cin_is_cpp_extern_c(l))
+ {
+ amount += curbuf->b_ind_cpp_extern_c
+ - added_to_amount;
+ break;
+ }
if (cin_nocode(l))
continue;
diff --git a/src/structs.h b/src/structs.h
index 5745df2ae9..475280af12 100644
--- a/src/structs.h
+++ b/src/structs.h
@@ -2236,6 +2236,7 @@ struct file_buffer
int b_ind_hash_comment;
int b_ind_cpp_namespace;
int b_ind_if_for_while;
+ int b_ind_cpp_extern_c;
#endif
linenr_T b_no_eol_lnum; /* non-zero lnum when last line of next binary
diff --git a/src/testdir/test_cindent.vim b/src/testdir/test_cindent.vim
index 5685c2be66..444c4c4109 100644
--- a/src/testdir/test_cindent.vim
+++ b/src/testdir/test_cindent.vim
@@ -14,3 +14,63 @@ func Test_cino_hash()
call assert_equal(["#include <iostream>", "#include"], getline(1,2))
bwipe!
endfunc
+
+func Test_cino_extern_c()
+ " Test for cino-E
+
+ let without_ind = [
+ \ '#ifdef __cplusplus',
+ \ 'extern "C" {',
+ \ '#endif',
+ \ 'int func_a(void);',
+ \ '#ifdef __cplusplus',
+ \ '}',
+ \ '#endif'
+ \ ]
+
+ let with_ind = [
+ \ '#ifdef __cplusplus',
+ \ 'extern "C" {',
+ \ '#endif',
+ \ "\tint func_a(void);",
+ \ '#ifdef __cplusplus',
+ \ '}',
+ \ '#endif'
+ \ ]
+ new
+ setlocal cindent cinoptions=E0
+ call setline(1, without_ind)
+ call feedkeys("gg=G", 'tx')
+ call assert_equal(with_ind, getline(1, '$'))
+
+ setlocal cinoptions=E-s
+ call setline(1, with_ind)
+ call feedkeys("gg=G", 'tx')
+ call assert_equal(without_ind, getline(1, '$'))
+
+ setlocal cinoptions=Es
+ let tests = [
+ \ ['recognized', ['extern "C" {'], "\t\t;"],
+ \ ['recognized', ['extern "C++" {'], "\t\t;"],
+ \ ['recognized', ['extern /* com */ "C"{'], "\t\t;"],
+ \ ['recognized', ['extern"C"{'], "\t\t;"],
+ \ ['recognized', ['extern "C"', '{'], "\t\t;"],
+ \ ['not recognized', ['extern {'], "\t;"],
+ \ ['not recognized', ['extern /*"C"*/{'], "\t;"],
+ \ ['not recognized', ['extern "C" //{'], ";"],
+ \ ['not recognized', ['extern "C" /*{*/'], ";"],
+ \ ]
+
+ for pair in tests
+ let lines = pair[1]
+ call setline(1, lines)
+ call feedkeys(len(lines) . "Go;", 'tx')
+ call assert_equal(pair[2], getline(len(lines) + 1), 'Failed for "' . string(lines) . '"')
+ endfor
+
+
+
+ bwipe!
+endfunc
+
+" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/version.c b/src/version.c
index 1c5dea4c1b..a859cf51fc 100644
--- a/src/version.c
+++ b/src/version.c
@@ -765,6 +765,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 431,
+/**/
430,
/**/
429,