Êíèãà: Learning GNU Emacs, 3rd Edition

9.3.3 Additional C and C++ Mode Features

9.3.3 Additional C and C++ Mode Features

C mode contains a number of other useful features, ranging from the generally useful to the arcanely obscure. Perhaps the most interesting of these are two ways of adding additional electric functionality to certain keystrokes, called auto-newline and hungry-delete-key.[64]

When auto-newline is enabled, it causes Emacs to add a newline character and indent the new line properly whenever you type a semicolon (;), curly brace ({ or }), or, at certain times, comma (,) or colon (:). These features can save you some time and help you format your code in a consistent style.

Auto-newline is off by default. To turn it on, type C-c C-a for c-toggle-auto-state. (Repeat the same command to turn it off again.) You will see the (C) in the mode line change to (C/a) as an indication. As an example of how it works, try typing in the code for our times( ) function. Type the first two lines up to the y on the second line:

int times (x, y)
int x, y
_

Now press the semicolon; notice that Emacs inserts a newline and brings you down to the next line:

int times (x, y)
int x, y;

_

Type the opening curly brace, and it happens again:

int times (x, y)
int x, y;
{

  _

Of course, the number of spaces Emacs indents after you type the { depends on the indentation style you are using.

The other optional electric feature, hungry-delete-key, is also off by default. To toggle it on, type C-c C-d (for c-toggle-hungry-state). You will see the (C) on the mode line change to (C/h), or if you have auto-newline turned on, from (C/a) to (C/ah).

Turning on hungry-delete-key empowers the Del key to delete all whitespace to the left of the point. To go back to the previous example, assume you just typed the open curly brace. Then, if you press Del, Emacs deletes everything back to the curly brace:

int times (x, y)
int x, y;
{
_

You can toggle the states of both auto-newline and hungry-delete-key with the command C-c C-t (for c-toggle-auto-hungry-state).

If you want either of these features on by default when you invoke Emacs, you can put lines like the following in your .emacs file:

(add-hook 'c-mode-hook
       '(lambda ( )
          (c-toggle-auto-state)))

If you want to combine this customization with another C mode customization, such as the indentation style in the previous example, you need to combine the lines of Emacs Lisp code as follows:

(add-hook 'c-mode-hook
       '(lambda ( )
          (c-set-style "stylename")
           (c-toggle-auto-state)))

Again, we will see what this hook construct means in "Customizing Existing Modes" in Chapter 11.

C mode also provides support for comments; earlier in the chapter, we saw examples of this support. There is, however, another feature. You can customize M-j (for indent-new-comment-line) so that Emacs continues the same comment on the next line instead of creating a new pair of delimiters. The variable comment-multi-line controls this feature: if it is set to nil (the default), Emacs generates a new comment on the next line, as in the example from earlier in the chapter:

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

This outcome is the result of typing M-j after multiplicand, and it shows that the cursor is positioned so that you can type the text of the second comment line. However, if you set comment-multi-line to t (or any value other than nil), you get this outcome instead:

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

The final feature we'll cover is C-c C-e, (for c-macro-expand). Like the conditional compilation motion commands (e.g., C-c C-u for c-up-conditional), c-macro-expand helps you answer the often difficult question, "What code actually gets compiled?" when your source code contains a morass of preprocessor directives.

To use c-macro-expand, you must first define a region. Then, when you type C-c C-e, it takes the code within the region, passes it through the actual C preprocessor, and places the output in a window called *Macroexpansion*.

To see how this procedure works, let's go back to the code example from earlier in this chapter that contains C preprocessor directives:

#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

If you define a region around this chunk of code and type C-c C-e, you see following the message:

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

followed by this:

done

Then you see a *Macroexpansion* window that contains this result:

*ptyv = open ("/dev/ptc", O_RDWR | O_NDELAY, 0);
if (fd < 0)
    return -1;

If you want to use c-macro-expand with a different C preprocessor command, instead of the default /lib/cpp -C (the -C option means "preserve comments in the output"), you can set the variable c-macro-preprocessor. For example, if you want to use an experimental preprocessor whose filename is /usr/local/lib/cpp, put the following line in your .emacs file:

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

It's highly recommended that you keep the -C option for not deleting comments in your code.

Îãëàâëåíèå êíèãè


Ãåíåðàöèÿ: 1.863. Çàïðîñîâ Ê ÁÄ/Cache: 3 / 1
ïîäåëèòüñÿ
Ââåðõ Âíèç