<< Back to man.ChinaUnix.net

INDENT

*indent.txt*    For Vim version 6.3.    最近更新: 2005年3月


                  VIM REFERENCE MANUAL    by Bram Moolenaar
                     译者: wandys http://vimcdoc.sf.net


本文讨论 C 程序以及其它文件类型的缩进。

1. 缩进 C 程序                      |C-indenting|
2. 按表达式缩进                   |indent-expression|


1. 缩进 C 程序                                              *C-indenting*

有关 C 缩进的基本操作请参用户手册的 |30.2|.

Vim 有很多自动缩进 C 程序的选项。这些选项只对缩进有影响而不处理其他形式的格式
化。若要对注释格式化,请参考 |format-comments|.

备注 如果编译时没有指定 |+smartindent| 或者 |+cindent|, 这些选项将不起作用。

实际上有四种可用缩进的方式:
'autoindent'    沿用上一行的缩进。
'smartindent'   类似 'autoindent', 但是可以识别一些 C 语法以能在合适的地方
                增加 / 减少缩进。
'cindent'       比上面两个更聪明;可以设置不同的缩进风格。
'indentexpr'    最灵活的一个: 根据表达式来计算缩进。若此选项非空,则将其他选
                项覆盖。参见 |indent-expression|.

本节下面的内容介绍 'cindent' 选项。

注意'cindent' 缩进不一定对所有的代码都起作用。Vim 不是 C 编译器: 它不能识别
出所有的语法。

这四个选项控制 C 程序缩进:
'cindent'       使 Vim 对 C 程序自动缩进。
'cinkeys'       指定在插入模式下按哪个键可以再次缩进。
'cinoptions'    设定你喜好的缩进模式。
'cinwords'      定义在下一行中开始一个额外缩进的关键字。

如果 'lisp' 选项没被打开并且 'equalprg' 为空, "=" 操作符将使用 Vim 的内建算法
而不调用外部程序。

若要对 C 文件自动设定 'cindent' 选项,请参考 |autocommand|.

                                        *cinkeys-format* *indentkeys-format*
'cinkeys' 选项是这样的一个字符串: 控制 Vim 在输入特定字符后或是在特定上下文下
的缩进反应。备注 这不仅仅触发 C-缩进。 若 'indentexpr' 非空,将会使用
'indentkeys' 而不是 'cinkeys'. 'cinkeys' 和 'indentkeys' 的格式是一样的。

其省缺值是 "0{,0},0),:,0#,!^F,o,O,e". 解释如下:

        "0{"    如果输入 '{' 作为行首字符
        "0}"    如果输入 '}' 作为行首字符
        "0)"    如果输入 ')' 作为行首字符
        ":"     如果在标记或是 case 语句后输入 ':'
        "0#"    如果输入 '#' 作为行首字符
        "!^F"   如果输入 CTRL-F (它不会被插入)
        "o"     如果输入 <CR> 或是使用 "o" 命令
        "O"     如果使用 "O" 命令
        "e"     如果输入处于行首的 "else" 的第二个 'e'

可以加在键值前面的字符:
!       当 '!' 在一个键值前面,Vim 将不会插入那个键而是将当前行再次缩进。
        这可以用来定义一个再次缩进当前行的键。CTRL-F 是省缺的键。将 CTRL-I
        设定为这个键时要小心,因为 CTRL-I 用来表示 <Tab> 的 ASCII 码。

*       当 '*' 在一个键值前面,会在插入此键之前再次缩进当前行。如果 'cinkeys'
        包含 "*<Retern>", Vim 在开启一个新行之前再次缩进当前行。
0       当 '0' 在一个键值前面 (但出现在 '!' 或 '*' 之后),只有当此键是作为行
        首字符输入时,Vim 才再次缩进当前行。如果在 "=" 之前使用,只有行首有空
        白符时 Vim 才再次缩进当前行。

如果 '!' 和 '*' 都不在键值前,Vim 将在你输入那个键后再次缩进当前行。 因此 ';'
触发一个包含 ';' 本身在内的行内缩进。

特殊键:
<>      尖括号表示一个键名本身。例如: "<Up>", "<Ins>" (参见 |key-notation|).
^       以 '^' 开头的字符串表示一个控制字符。比如,"^F" 是 CTRL-F.
o       当使用 "o" 命令或是在当前行后开启一个新行时再次缩进当前行。
O       当使用 "O" 命令时再次缩进当前行。
e       当输入第二个 'e' 时,再次缩进由 "else" 开头的行。
:       在一个标记或是 case 语句后输入 ':' 时,再次缩进当前行; 不对 C++ 中的
        "class::method" 这种形式缩进。若要对所有的 ":" 都缩进,使用 "<:>".
=word   当输入 "word" 的最后一个字母时再次缩进。"word" 可以是一个单词的一部
        分。比如当输入 "endif" 或是 "endwhile" 中的 "d" 时,"=end" 都能引起
        再次缩进。但当输入 "bend" 时就没有反应。另外,当补齐功能产生了一个以
        "word" 开头的单词时也会再次缩进。"0=word" 是当单词前有空白符时才缩进。
=~word  类似 "=word", 但忽略大小写。

如果你想在输入 'o', 'O', 'e', '0', '<', '>', '*', ':',  '!' 时产生再次缩进,
请分别对这些建使用 "<o>", "<O>", "<e>", "<0>", "<<>", "<>>", "<*>", "<:>",
"<!>".

emacs 风格的缩进模式并不是每次输入 <Enter> 都缩进,而是只在输入 <Tab> 时
才缩进。对此,我建议使用:
        :set cinkeys=0{,0},:,0#,!<Tab>,!^F
你也许需要关掉 'autoindent' 选项。

备注: 如果你手动地改变了当前行的缩进,Vim 会忽略对此行的 cindent 设定。因此如
果你输入 <BS>, <Tab>, <Space>, CTRL-T, 或是 CTRL-D 改变了缩进,将会阻止 Vim
的再次缩进。

                                                *cinoptions-values*
'cinoptions' 选项决定 Vim 来如何进行缩进。在下面的列表中,"N" 表示一个你选择
的数字(可以为负数)。如果数字后有一个 's', Vim 将那个数字乘以 'shiftwidth':
"1s" 是 'shiftwidth', "2s" 是 'shiftwidth' 的两倍,以此类推。你也可以使用小数
点: "-0.5s" 是 'shiftwidth' 一半的负值。下面的例子假定 'shiftwidth' 为 4。

        >N    "一般" 缩进值。在需要增加缩进的行(比如,以 "if" 或是 "{"
              等开头的行)后使用。(省缺为 'shiftwidth').

                cino=               cino=>2             cino=>2s
                  if (cond)           if (cond)           if (cond)
                  {                   {                   {
                      foo;              foo;                      foo;
                  }                   }                   }

        eN    当 '{' 在行尾(更准确地,不在行首)时,相对'一般'缩进增加 N 个字
              符的缩进。如果你想对 '{' 在行首时和 '{' 在行尾时使用不同的缩进,
              这将很有用。(省缺为 0).

                cino=               cino=e2             cino=e-2
                  if (cond) {         if (cond) {         if (cond) {
                      foo;                  foo;            foo;
                  }                   }                   }
                  else                else                else
                  {                   {                   {
                      bar;                bar;                bar;
                  }                   }                   }

        nN    如果一个在 "if", "while" 等等后面的语句不在大括号内,则相对
              '一般'缩进增加 N 个字符的缩进。如果你要对语句前有 '{' 和没有
              '{' 使用不同的缩进,这将很有用。(省缺为 0).

                cino=               cino=n2             cino=n-2
                  if (cond)           if (cond)           if (cond)
                      foo;                  foo;            foo;
                  else                else                else
                  {                   {                   {
                      bar;                bar;                bar;
                  }                   }                   }

        fN    将函数或是其他代码块开头的 '{' 放在第 N 列. 这只对不包含于其他
              大括号内并且处于行首的 '{' 起作用。'{' 之后的代码对 '}' 的相对
              位置不变。 (省缺为 0)。

                cino=               cino=f.5s           cino=f1s
                  func()              func()              func()
                  {                     {                     {
                      int foo;              int foo;              int foo;

        {N    将 '{' 置于'一般'缩进后 N 个字符的位置。这只对包括在其他大括号
              内的 '{' 起作用。(省缺为 0).

                cino=               cino={.5s           cino={1s
                  if (cond)           if (cond)           if (cond)
                  {                     {                     {
                      foo;                foo;                foo;

        }N    将 '}' 放在与之匹配的 '{' 之后 N 个字符处。(省缺为 0)。

                cino=               cino={2,}-0.5s      cino=}2
                  if (cond)           if (cond)           if (cond)
                  {                     {                 {
                      foo;                foo;                foo;
                  }                   }                     }

        ^N    如果 '{' 在第 0 列,则对其包含的语句增加相对'一般'所进 N 个字
              符的缩进。这可以对整个函数设定一个不同的缩进。(有人喜欢将其设
              成负数)。(省缺为 0).

                cino=               cino=^-2            cino=^-s
                  func()              func()              func()
                  {                   {                   {
                      if (cond)         if (cond)         if (cond)
                      {                 {                 {
                          a = b;            a = b;            a = b;
                      }                 }                 }
                  }                   }                   }

        :N    将 case 标记放在 switch() 缩进位置之后的 N 个字符处。(省缺为
              'shiftwidth')。

                cino=               cino=:0
                  switch (x)          switch(x)
                  {                   {
                      case 1:         case 1:
                          a = b;          a = b;
                      default:        default:
                  }                   }

        =N    将 case 标记之后的语句放在标记缩进位置之后的 N 个字符处。(省缺为
              'shiftwidth')。

                cino=               cino==10
                   case 11:             case 11:  a = a + 1;
                       a = a + 1;                 b = b + 1;

        lN    如果 N 不为 0, Vim 将会和 case 标记对齐,而不是和其后同一行的语
              句对齐。

                cino=                       cino=l1
                    switch (a) {              switch (a) {
                        case 1: {                 case 1: {
                                    break;            break;
                                }                 }

        bN    如果 N 不为 0, Vim 会将 最后的 "break" 和 case 标记对齐,这样
              case..break 看起来有点像一个代码块。(省缺为 0)。

                cino=               cino=b1
                  switch (x)          switch(x)
                  {                   {
                      case 1:             case 1:
                          a = b;              a = b;
                          break;          break;

                      default:            default:
                          a = 0;              a = 0;
                          break;          break;
                  }                   }

        gN    将 C++ 作用域声明置于其所在代码块的 N 个字符后。(省缺为
              'shiftwidth')。作用域声明可以是 "public:", "protected:", 或者
              "private:"。

                cino=               cino=g0
                  {                   {
                      public:         public:
                          a = b;          a = b;
                      private:        private:
                  }                   }

        hN    将 C++ 作用域声明后面的语句置于对应标记的 N 个字符后。
              (省缺为 'shfitwidth')。

                cino=               cino=h10
                   public:              public:   a = a + 1;
                       a = a + 1;                 b = b + 1;

        pN    在 K&R 形式的函数声明中,将参数的声明放在 N 个字符的相对位置。
              (省缺为 'shiftwidth')。

                cino=               cino=p0             cino=p2s
                  func(a, b)          func(a, b)          func(a, b)
                      int a;          int a;                      int a;
                      char b;         char b;                     char b;

        tN    将函数返回值类型声明放在 N 个字符的相对位置. (省缺为
              'shiftwidth')。

                cino=               cino=t0             cino=t7
                      int             int                        int
                  func()              func()              func()

        iN    缩进 C++ 的基类声明和构造函数初始化,如果它们处于行首 (否则,
              和 ':' 的右半部分对齐)。(省缺为 'shiftwidth')。

                cino=                     cino=i0
                  class MyClass :           class MyClass :
                      public BaseClass      public BaseClass
                  {}                        {}
                  MyClass::MyClass() :      MyClass::MyClass() :
                      BaseClass(3)          BaseClass(3)
                  {}                        {}

        +N    将一个后继行缩进额外 N 个字符。(省缺为 'shiftwidth')。

                cino=                     cino=+10
                  a = b + 9 *               a = b + 9 *
                      c;                              c;

        cN    对缩进开头 (译者注: /*) 后面的行,如果 /* 所在行没有其它的字符,
              相对 /* 进行 N 个字符的缩进。(省缺为 3).
              参见 |format-comments|.

                cino=                     cino=c5
                  /*                        /*
                     text.                       text.
                   */                        */

        CN    如果 N 非零,像上面 c 选项一样对注释缩进,即使 /* 后面还有其他
              文字。

                cino=c0                   cino=c0,C1
                  /********                 /********
                    text.                   text.
                  ********/                 ********/
             (Example uses ":set comments& comments-=s1:/* comments^=s0:/*")

        /N    将注释行缩进 N 个字符。(省缺为 0)。
                cino=                     cino=/4
                  a = b;                    a = b;
                  /* comment */                 /* comment */
                  c = d;                    c = d;

        (N    在没有结束的括号内,对没有结束的括号所在行进行 N 个字符的缩进。
              对每一个没有结束的括号增加 'shiftwidth' 的缩进。如果 N 为 0,
              或没有结束的括号是其所在行的首个非空白字符,对其后的字符向上
              缩进。 (省缺为 'shiftwidth' * 2).

                cino=                     cino=(0
                  if (c1 && (c2 ||          if (c1 && (c2 ||
                              c3))                     c3))
                      foo;                      foo;
                  if (c1 &&                 if (c1 &&
                          (c2 || c3))           (c2 || c3))
                     {                         {

        uN    和 (N 一样,但更深一级。(省缺为 'shiftwidth').

                cino=                     cino=u2
                  if (c123456789            if (c123456789
                          && (c22345                && (c22345
                              || c3))                 || c3))

        UN    如果 N 非零,不忽略 ( 或是 u 指定的缩进以免没结束的括号是所在
              行的首个非空白字符。(省缺为 0).

                cino= or cino=(s          cino=(s,U1
                  c = c1 &&                 c = c1 &&
                      (                         (
                       c2 ||                        c2 ||
                       c3                           c3
                      ) && c4;                  ) && c4;

        wN    在没有结束的括号内并且 N 非零,使用 "(0" 或是 "u0", 或当没有结
              结束的括号是所在行的首个非空白字符,对紧随没结束括号后的字符而
              不是首个非空白字符缩进。(省缺为 0).

                cino=(0                   cino=(0,w1
                  if (   c1                 if (   c1
                         && (   c2              && (   c2
                                || c3))             || c3))
                      foo;                      foo;

        WN    在没有结束的括号内并且 N 非零,使用 "(0" 或是 "u0", 或当没有结
              结束的括号是所在行的首个非空白字符并且它不是最后一个结束的括号,
              对下一行进行相对外部代码块 (比如,行首或是下一个没结束的括号)
              N 个字符的缩进。(省缺为 0).

                cino=(0                    cino=(0,W4
                  a_long_line(              a_long_line(
                              argument,         argument,
                              argument);        argument);
                  a_short_line(argument,    a_short_line(argument,
                               argument);                argument);

        mN    如果 N 非零,则将 ')' 所在行和与其匹配的 ')' 所在行对齐。
              (省缺为 0).

                cino=(s                   cino=(s,m1
                  c = c1 && (               c = c1 && (
                      c2 ||                     c2 ||
                      c3                        c3
                      ) && c4;              ) && c4;
                  if (                      if (
                      c1 && c2                  c1 && c2
                     )                      )
                      foo;                      foo;

                                        *java-cinoptions* *java-indenting*
        jN    正确地缩进 java 匿名类。目前,'N' 的值并没有用到但其不能为 0
              (比如 'j1'). 'j1' 将对下面的代码断这样正确的缩进:

                object.add(new ChangeListener() {
                    public void stateChanged(ChangeEvent e) {
                        do_something();
                    }
                });

        )N    Vim 最多在 N 行范围内查找没有结束的括号。这将缩小 Vim 用来查找
              括号的时间。

        *N    Vim 最多在 N 行范围内查找没有结束的注释。这将缩小 Vim 用来查找
              注释开头的时间。(省缺 30 行).


全部的省缺值是:
        cinoptions=>s,e0,n0,f0,{0,}0,^0,:s,=s,l0,gs,hs,ps,ts,+s,c3,C0,(2s,us,
                   \U0,w0,m0,j0,)20,*30

Vim 将一行从第一列开始,如果:
- 它以 '#' 开头,并且 'cinkeys' 包含 '#'.
- 它以一个标记 (后面跟随一个 ':' 的关键字,而不是 "case" 或 "default") 开头。
- 任何缩进的组合使这一行产生小于 0 的缩进。


2. 按表达式缩进                                           *indent-expression*

关于灵活缩进的一些基本设置在用户手册的 |30.3| 有解释。

如果你要写一个自己的缩进文件,它必须设定 'indentexpr' 选项。设定 'indentkeys'
也经常有用。$VIMRUNTIME/indent 目录下有例子可以参考。


REMARKS ABOUT SPECIFIC INDENT FILES 


FORTRAN                                                 *fortran-indent*

if, select case, 和 where 代码块被缩进。如果 Fortran 在自由格式下,注释,标号
语句和续行被缩进; 如果在固定格式下,这些就不会被缩进,因为左边要求留出空白。
因此,在固定格式下,需要手动对标号语句和续行缩进。关于检测源码格式的更深入
讨论,参见 |fortran-syntax|.

Do loops 
缺省情况下,所有的 do 循环保持原样,不缩进。在 Fortran 里,循环甚至是多重循环
可以结束于一个任意类型标号语句,使得 do 循环非结构化。对其正确的缩进需要编译器
级别的语法分析。对于这样 do 循环结束于标号语句的老式代码可以使用 Tidy
(http://www.unb.ca/chem/ajit/f_tidy.htm) 等专门的程序缩进。结构化的
do/continue 循环也保持不缩进,因为 continue 除作为 do 循环结束标记外还有其它的
用途。Tidy 可以将结构化的 do/continue 循环转换成 do/enddo 的形式。do/enddo 类
型的循环能被缩进。如果你只使用结构化的 do/enddo 形式的循环你可以在你的 .vimrc
中作如下声明:

   let fortran_do_enddo=1

这样 do 循环就被缩进了。如果你的循环只是在比如 .f90 文件里出现的 do/enddo 形
式的缩进,可以像下面一样用 autocommand 命令设置一个缓冲区标记

  au! BufRead,BufNewFile *.f90 let b:fortran_do_enddo=1

使 .f90 文件里的 do 循环被缩进而在其它文件比如 .for 文件中不被缩进。


VERILOG                                                 *verilog-indent*

一般的代码块,像 if, for, case, always, initial, function, specify, begin
等等都被缩进。module 代码块 (处于第一级) 省缺不被缩进。你可以在 .vimrc 里
打开这个缩进:

  let b:verilog_indent_modules = 1

这样 module 代码块就被缩进。要关闭缩进,删除这个变量:

  :unlet b:verilog_indent_modules

要只对 Verilog 文件设定变量,可以这样做:

  au BufReadPost * if exists("b:current_syntax")
  au BufReadPost *   if b:current_syntax == "verilog"
  au BufReadPost *     let b:verilog_indent_modules = 1
  au BufReadPost *   endif
  au BufReadPost * endif

另外,可以设定 b:verilog_indent_width 来改变缩进值 (省缺为 'shiftwidth):
  let b:verilog_indent_width = 4
  let b:verilog_indent_width = &sw * 2

你还可以打开 verbose 模式来帮助调试:

  let b:verilog_indent_verbose = 1

不要忘了要先设定 ":set cmdheight=2" 才能显示信息。

 vim:tw=78:ts=8:ft=help:norl:

Generated by vim2html on Fri Mar 25 20:03:47 GMT 2005