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

9.3.1 Motion Commands

9.3.1 Motion Commands

In addition to the standard Emacs commands for words and sentences (which are mainly useful only inside multiline comments), C mode contains advanced commands that know about statements, functions,[63] and preprocessor conditionals. A summary of these commands appears in Table 9-3.

Table 9-3. Advanced C motion commands

Keystrokes Command name Action
M-a c-beginning-of-statement Move to the beginning of the current statement.
M-e c-end-of-statement Move to the end of the current statement.
M-q c-fill-paragraph If in comment, fill the paragraph, preserving indentations and decorations.
C-M-a beginning-of-defun Move to the beginning of the body of the function surrounding the point.
C-M-e end-of-defun Move to the end of the function.
C-M-h c-mark-function Put the cursor at the beginning of the function, the mark at the end.
C-c C-q c-indent-defun Indent the entire function according to indentation style.
C-c C-u c-up-conditional Move to the beginning of the current preprocessor conditional.
C-c C-p c-backward-conditional Move to the previous preprocessor conditional.
C-c C-n c-forward-conditional Move to the next preprocessor conditional.

Notice that the statement motion commands have the same key bindings as backward-sentence and forward-sentence, respectively. In fact, they act as sentence commands if you use them within a C comment.

Similarly, M-q is normally the fill-paragraph command; C mode augments it with the ability to preserve indentations and decorative characters at the beginnings of lines. For example, if your cursor is anywhere in this comment:

/* This is
* a
* comment paragraph with wildly differing right
* margins.
* It goes on     for a while,
* then stops. */

typing M-q has this result:

/* This is a comment paragraph with wildly differing right margins.
* It goes on for a while, then stops. */

You will find that the preprocessor conditional motion commands are a godsend if you have to slog through someone else's voluminous code. Especially if you're faced with code built to run on a variety of systems—like Emacs itself—often the most important question you need answered is, "What code is actually compiled?"

With C-c C-u, you can tell instantly what preprocessor conditional governs the code in question. Consider this code block:

#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

Imagine that the ellipses (...) represent hundreds of lines of code. Now suppose you are trying to determine under what conditions the file /dev/ptc is opened. If your cursor is on that line of code, you can type C-c C-u, and the cursor moves to the line #ifdef LUCYX—telling you that the code is compiled if you're on a LUCYX system. If you want to skip the code that would not be compiled and go directly to the end of the conditional, type C-c C-n. We will see another command that is useful for dealing with C preprocessor code later in this section.

C statement and statement block delimiter characters are bound to commands that, in addition to inserting the appropriate character, also provide proper indentation. These characters are {, }, ;, and : (for labels and switch cases). For example, if you are closing out a statement block or function body, you can press C-j (or Enter) and type }, and Emacs lines it up with its matching {. This eliminates the need for you to scroll back through the code to find out what column the { is in.

Because } is a parenthesis-type character, Emacs attempts to "flash" a matching { when you type }. If the matching { is outside of the text displayed in your window, Emacs instead prints the line containing the { in the minibuffer. Furthermore, if only whitespace (blanks or tabs) follows the { on its line, Emacs also prints a ^J (for C-j) followed by the next line, thus giving a better idea of the context of the {.

Recall the "times" example earlier in this chapter. Let's say you are typing in a } to end the function, and the { that begins the function body is off-screen. There is no code on the line following the beginning {, so you see the following in the minibuffer after you type }:

Matches {^J int i;

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


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