Skip to content

Commit 7720ba8

Browse files
committed
patch 8.0.0431: 'cinoptions' cannot set indent for extern block
Problem: 'cinoptions' cannot set indent for extern block. Solution: Add the "E" flag in 'cinoptions'. (Hirohito Higashi)
1 parent bb96226 commit 7720ba8

File tree

5 files changed

+145
-3
lines changed

5 files changed

+145
-3
lines changed

runtime/doc/indent.txt

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,21 @@ The examples below assume a 'shiftwidth' of 4.
324324
{ {
325325
void function(); void function();
326326
} }
327+
<
328+
*cino-E*
329+
EN Indent inside C++ linkage specifications (extern "C" or
330+
extern "C++") N characters extra compared to a normal block.
331+
(default 0).
332+
333+
cino= cino=E-s >
334+
extern "C" { extern "C" {
335+
void function(); void function();
336+
} }
337+
338+
extern "C" extern "C"
339+
{ {
340+
void function(); void function();
341+
} }
327342
<
328343
*cino-p*
329344
pN Parameter declarations for K&R-style function declarations will
@@ -554,7 +569,7 @@ The examples below assume a 'shiftwidth' of 4.
554569

555570

556571
The defaults, spelled out in full, are:
557-
cinoptions=>s,e0,n0,f0,{0,}0,^0,L-1,:s,=s,l0,b0,gs,hs,N0,ps,ts,is,+s,
572+
cinoptions=>s,e0,n0,f0,{0,}0,^0,L-1,:s,=s,l0,b0,gs,hs,N0,E0,ps,ts,is,+s,
558573
c3,C0,/0,(2s,us,U0,w0,W0,k0,m0,j0,J0,)20,*70,#0
559574

560575
Vim puts a line in column 1 if:

src/misc1.c

Lines changed: 66 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5809,6 +5809,54 @@ cin_is_cpp_namespace(char_u *s)
58095809
return FALSE;
58105810
}
58115811

5812+
/*
5813+
* Recognize a `extern "C"` or `extern "C++"` linkage specifications.
5814+
*/
5815+
static int
5816+
cin_is_cpp_extern_c(char_u *s)
5817+
{
5818+
char_u *p;
5819+
int has_string_literal = FALSE;
5820+
5821+
s = cin_skipcomment(s);
5822+
if (STRNCMP(s, "extern", 6) == 0 && (s[6] == NUL || !vim_iswordc(s[6])))
5823+
{
5824+
p = cin_skipcomment(skipwhite(s + 6));
5825+
while (*p != NUL)
5826+
{
5827+
if (vim_iswhite(*p))
5828+
{
5829+
p = cin_skipcomment(skipwhite(p));
5830+
}
5831+
else if (*p == '{')
5832+
{
5833+
break;
5834+
}
5835+
else if (p[0] == '"' && p[1] == 'C' && p[2] == '"')
5836+
{
5837+
if (has_string_literal)
5838+
return FALSE;
5839+
has_string_literal = TRUE;
5840+
p += 3;
5841+
}
5842+
else if (p[0] == '"' && p[1] == 'C' && p[2] == '+' && p[3] == '+'
5843+
&& p[4] == '"')
5844+
{
5845+
if (has_string_literal)
5846+
return FALSE;
5847+
has_string_literal = TRUE;
5848+
p += 5;
5849+
}
5850+
else
5851+
{
5852+
return FALSE;
5853+
}
5854+
}
5855+
return has_string_literal ? TRUE : FALSE;
5856+
}
5857+
return FALSE;
5858+
}
5859+
58125860
/*
58135861
* Return a pointer to the first non-empty non-comment character after a ':'.
58145862
* Return NULL if not found.
@@ -6652,6 +6700,7 @@ cin_skip2pos(pos_T *trypos)
66526700
{
66536701
char_u *line;
66546702
char_u *p;
6703+
char_u *new_p;
66556704

66566705
p = line = ml_get(trypos->lnum);
66576706
while (*p && (colnr_T)(p - line) < trypos->col)
@@ -6660,8 +6709,11 @@ cin_skip2pos(pos_T *trypos)
66606709
p = cin_skipcomment(p);
66616710
else
66626711
{
6663-
p = skip_string(p);
6664-
++p;
6712+
new_p = skip_string(p);
6713+
if (new_p == p)
6714+
++p;
6715+
else
6716+
p = new_p;
66656717
}
66666718
}
66676719
return (int)(p - line);
@@ -6977,6 +7029,9 @@ parse_cino(buf_T *buf)
69777029
/* indentation for # comments */
69787030
buf->b_ind_hash_comment = 0;
69797031

7032+
/* Handle C++ extern "C" or "C++" */
7033+
buf->b_ind_cpp_extern_c = 0;
7034+
69807035
for (p = buf->b_p_cino; *p; )
69817036
{
69827037
l = p++;
@@ -7051,6 +7106,7 @@ parse_cino(buf_T *buf)
70517106
case '#': buf->b_ind_hash_comment = n; break;
70527107
case 'N': buf->b_ind_cpp_namespace = n; break;
70537108
case 'k': buf->b_ind_if_for_while = n; break;
7109+
case 'E': buf->b_ind_cpp_extern_c = n; break;
70547110
}
70557111
if (*p == ',')
70567112
++p;
@@ -7764,6 +7820,8 @@ get_c_indent(void)
77647820
l = skipwhite(ml_get_curline());
77657821
if (cin_is_cpp_namespace(l))
77667822
amount += curbuf->b_ind_cpp_namespace;
7823+
else if (cin_is_cpp_extern_c(l))
7824+
amount += curbuf->b_ind_cpp_extern_c;
77677825
}
77687826
else
77697827
{
@@ -7990,6 +8048,12 @@ get_c_indent(void)
79908048
- added_to_amount;
79918049
break;
79928050
}
8051+
else if (cin_is_cpp_extern_c(l))
8052+
{
8053+
amount += curbuf->b_ind_cpp_extern_c
8054+
- added_to_amount;
8055+
break;
8056+
}
79938057

79948058
if (cin_nocode(l))
79958059
continue;

src/structs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2236,6 +2236,7 @@ struct file_buffer
22362236
int b_ind_hash_comment;
22372237
int b_ind_cpp_namespace;
22382238
int b_ind_if_for_while;
2239+
int b_ind_cpp_extern_c;
22392240
#endif
22402241

22412242
linenr_T b_no_eol_lnum; /* non-zero lnum when last line of next binary

src/testdir/test_cindent.vim

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,63 @@ func Test_cino_hash()
1414
call assert_equal(["#include <iostream>", "#include"], getline(1,2))
1515
bwipe!
1616
endfunc
17+
18+
func Test_cino_extern_c()
19+
" Test for cino-E
20+
21+
let without_ind = [
22+
\ '#ifdef __cplusplus',
23+
\ 'extern "C" {',
24+
\ '#endif',
25+
\ 'int func_a(void);',
26+
\ '#ifdef __cplusplus',
27+
\ '}',
28+
\ '#endif'
29+
\ ]
30+
31+
let with_ind = [
32+
\ '#ifdef __cplusplus',
33+
\ 'extern "C" {',
34+
\ '#endif',
35+
\ "\tint func_a(void);",
36+
\ '#ifdef __cplusplus',
37+
\ '}',
38+
\ '#endif'
39+
\ ]
40+
new
41+
setlocal cindent cinoptions=E0
42+
call setline(1, without_ind)
43+
call feedkeys("gg=G", 'tx')
44+
call assert_equal(with_ind, getline(1, '$'))
45+
46+
setlocal cinoptions=E-s
47+
call setline(1, with_ind)
48+
call feedkeys("gg=G", 'tx')
49+
call assert_equal(without_ind, getline(1, '$'))
50+
51+
setlocal cinoptions=Es
52+
let tests = [
53+
\ ['recognized', ['extern "C" {'], "\t\t;"],
54+
\ ['recognized', ['extern "C++" {'], "\t\t;"],
55+
\ ['recognized', ['extern /* com */ "C"{'], "\t\t;"],
56+
\ ['recognized', ['extern"C"{'], "\t\t;"],
57+
\ ['recognized', ['extern "C"', '{'], "\t\t;"],
58+
\ ['not recognized', ['extern {'], "\t;"],
59+
\ ['not recognized', ['extern /*"C"*/{'], "\t;"],
60+
\ ['not recognized', ['extern "C" //{'], ";"],
61+
\ ['not recognized', ['extern "C" /*{*/'], ";"],
62+
\ ]
63+
64+
for pair in tests
65+
let lines = pair[1]
66+
call setline(1, lines)
67+
call feedkeys(len(lines) . "Go;", 'tx')
68+
call assert_equal(pair[2], getline(len(lines) + 1), 'Failed for "' . string(lines) . '"')
69+
endfor
70+
71+
72+
73+
bwipe!
74+
endfunc
75+
76+
" vim: shiftwidth=2 sts=2 expandtab

src/version.c

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

765765
static int included_patches[] =
766766
{ /* Add new patch number below this line */
767+
/**/
768+
431,
767769
/**/
768770
430,
769771
/**/

0 commit comments

Comments
 (0)