跟小弟我学习GNU Emacs - 14

跟我学习GNU Emacs - 14

 

4.3.3 C和C++模式的附加功能

C模式还有很多非常有价值的功能,有的用途广泛,有的仅适用于极其罕见的情况。自动开始新行(auto-newline)和“饥饿的删除键(hungry-delete-key)”可以说是这些功能中最有意思的两个了,他们是两种用来给按键操作增加自动缩进功能的办法。

启动了自动开始新行功能之后,只要一输入分号“;”、花括号“{”和“}”或者(在某些特定场合下)逗号“,”及冒号“:”,Emacs就会自动加上一个换行符并对新行做正确的缩进。这项功能可以节省一些时间,而且能够帮助保持代码书写风格的一致性。

自动开始新行功能在默认的情况下是处于禁用状态的;可以用“C-c C-a”组合键(命令名是c-toggle-auto-state)启用它。(重复这个命令将再次禁用这项功能),状态行上的“(C)”标志改变为“(C/a)”。我们以times()函数为例来看看它究竟是怎样工作的。先输入头两行代码,当输入了第2行上的“y”时,我们看到的是:

int times (x, y)

int x, y▕

 

    现在,按下分号键“;”,Emacs将插入一个换行符并把光标移到下一行,如下所示:

int times (x, y)

int x, y;

▌

 

    输入左花括号,同样的事情将再次发生,如下所示:

int times (x, y)

int x, y;

{

   ▌

当然,Emacs在输入“{”之后的缩进量要取决于正在使用的缩进样式。

 

另一种可选用的自动缩进功能即“饥饿的删除键”,他在默认的情况下也是处于禁用状态的。可以用“C-c C-d”组合键(命令名是c-toggle-huangry-state)启用之。状态行上的“(C)”标志为“(C/h)”;或者,如果已经启用了自动开始新行功能,状态行上的“(C/a)”标志将改变为“(C/ah)”。

“饥饿的删除键”功能将使Del键具备删除光标左面全部空白的能力。我们还用刚才的例子接着往下说。假设刚输入那个左花括号。现在,如果按下DEL键,则Emacs将一直删到这个左花括号处,如下所示:

 

int times (x, y)

int x, y;

{ 

 

自动开始新行和“饥饿的删除键”这两种功能的启用/禁用状态可以同时用“C-c C-t”组合键(命令名是c-toggle-auto-huangry-state)进行切换。

如果让这两项功能中的某一种在启动Emacs的时候自动处于启用状态,就需要把下面这样的语句添加到“.eamacs”文件里:

(add-hook 'c-mode-hook

(add-hook 'c-mode-hook

      '(lambda ( )

         (c-toggle-auto-state)))

 

    如果想用另外的C模式定制来合并这个定制(如前例中的缩进样式),就需要将Emacs LISP代码行合并如下:

(add-hook 'c-mode-hook

      '(lambda ( )

         (c-set-style "stylename")

          (c-toggle-auto-state)))

 

C模式还提供一些与程序注释有关的支持功能。在本章前面的内容里,我们已经对这方面的支持功能做过概括性的讨论,但并没有对某种编辑模式在这方面的具体功能做细致的说明。大家可以对“M-j”(命令名是indent-new-comment-line)的执行情况进行定制,从而使Emacs在下一行继续同一条注释,而不是另外创建一组新的注释分隔符。这项功能是由变量comment-multi-line控制的:如果它设置为“nil”,Emacs就将在下一行创建一条新的注释,就像在本章前面的示例中所给出的那样,如下所示:

result += y;                    /* add the multiplicand */

                                /* */

 

    在输入单词“multiplicand”之后,立刻按下“M-j”组合键就会得到这样的结果;现在的光标位置表示可以立刻开始输入第二个注释行上的文本。如果把变量comment-multi-line设置为“t”(或者任意一个不是“nil”的值),将得到如下所示的结果:

 

result += y;                    /* add the multiplicand 

                                   */

 

我们将要介绍的最后一个功能是“C-c C-e”组合键(命令名是c-macro-expand)。和以预处理器条件为单位的移动命令(比如绑定在“C-c C-u”组合键上的c-up-conditional命令)一样,c-macro-expand命令也能帮助回答“到底有哪些代码是真正会被编译的?”这个通常很难回答的问题。

在使用c-macro-expand命令之前,必须先定义一个文本块。接着,按下“C-cC-e”组合键时,这个文本块中的代码将被送往实际的C语言预处理器去进行处理,其结果将被放到一个名我“*Macroexpansion*”的窗口里。

看下面的例子:

 

#define LUCYX

#define BADEXIT -1



#ifdef LUCYX

    *ptyv = open ("/dev/ptc", O_RDWR | O_NDELAY, 0);

    if (fd < 0)

        return BADEXIT;

#else

    fprintf (stderr, "You can't do that on this system!");

#endif

 

    如果把这段代码定义为一个文本块并按下“C-c C-e”组合键,那么就会出现下面这条消息:

 

Invoking /lib/cpp -C on region...

 

过一会儿,出现

 

done

 

    接下来,出现一个“*Macroexpansion*”窗口,窗口里是这次处理的结果:

 

*ptyv = open ("/dev/ptc", O_RDWR | O_NDELAY, 0);

    if (fd < 0)

        return -1;

 

    如果想让c-macro-expand调用另外一个c预处理器命令而不是默认的“/lib/cpp -C”(选项“-C”表示“把注释保留在输出里”),就需要对变量c-macro-preprocessor做相应的设置。比如,如果想试用文件名是“/usr/local/lib/cpp”的预处理器,就需要把下面这条语句添加到“.emacs”文件里:

 

(setq c-macro-preprocessor "/usr/local/lib/cpp -C")

 

    我们强烈建议大家保留“-C”选项以免预处理器删掉代码中的注释。