]> granicus.if.org Git - vim/commitdiff
patch 8.0.0431: 'cinoptions' cannot set indent for extern block v8.0.0431
authorBram Moolenaar <Bram@vim.org>
Wed, 8 Mar 2017 21:19:26 +0000 (22:19 +0100)
committerBram Moolenaar <Bram@vim.org>
Wed, 8 Mar 2017 21:19:26 +0000 (22:19 +0100)
Problem:    'cinoptions' cannot set indent for extern block.
Solution:   Add the "E" flag in 'cinoptions'. (Hirohito Higashi)

runtime/doc/indent.txt
src/misc1.c
src/structs.h
src/testdir/test_cindent.vim
src/version.c

index fdb7c67edbdd97d8b5941981858e51a9f8e3fba7..efb0a7d79225f8e70e19e1dfd9ff30982dc20c47 100644 (file)
@@ -324,6 +324,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
@@ -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:
index ec92f037574716a5a902a4c5f4a803581825b430..c6b8d13b78b018f5b50312850b6fcfb133b92ade 100644 (file)
@@ -5809,6 +5809,54 @@ cin_is_cpp_namespace(char_u *s)
     return FALSE;
 }
 
+/*
+ * 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.
@@ -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;
index 5745df2ae91c119a8b37e66224d6a20bf20c6037..475280af12dc7ea15d56cde6cb70f4e5a0674166 100644 (file)
@@ -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
index 5685c2be667bcd3ca5b5255a9dac7fa7d55c74f4..444c4c4109fb98a3bca3f7927a1d75939bbdc269 100644 (file)
@@ -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
index 1c5dea4c1b22be9df14a4972aac0c53d637d5890..a859cf51fc0ba13c27865ad3a000d399500ac4dc 100644 (file)
@@ -764,6 +764,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    431,
 /**/
     430,
 /**/