Tutorial: Emacs for Programmers

 in
Ever wanted an all-in-one program development, compilation, and debugging environment? Look no further than Emacs.

Those of you who tuned in last month will recall “Emacs: Friend or Foe?”, a tutorial for people who can't stand anything but vi. “All right,” you're asking yourselves, “What is this card-carrying vi fundamentalist doing writing yet another article on Emacs?” Sounds fishy, doesn't it?

The truth is, once you get the hang of it, Emacs can greatly simplify editing, especially editing program source code. I now routinely use Emacs for developing and debugging programs.

It dramatically reduces turnaround time during the dreaded edit-compile-curse-debug-edit cycle. Here's how to put Emacs to use in this manner.

The bulk of this tutorial assumes that you are familiar with Emacs, as well as with customizing your Emacs environment (as discussed in last month's tutorial, in Linux Journal volume 1, issue 5). As long as you know how to add code to your .emacs startup file (or, as per last month's discussion, ~/emacs/startup.el), you're set.

The functions and comments described here work with GNU Emacs 19.24.1. By the time you read this article, newer versions may be available, in which case your mileage may vary.

Editing C Code

As you know, Emacs has several major modes associated with programming. For example, C Mode is used for editing C source, Perl Mode for Perl, and so on. First off, I'll discuss the features of C Mode, and then explain how to compile and debug C programs within Emacs.

The command M-x c-mode is used to enter C Mode. (Recall from last month: M-x is Meta-x where meta is usually the <esc> key.) However, Emacs is usually able to determine that C Mode should be used for a C source file, either by the filename extension .c, or if the magic string

-*- C -*-

appears on the first line of the file. See the Emacs documentation on major modes if you're interested in how this works.

Within C Mode, code is automatically indented according to the values of several variables. These variables include c-indent-level, c-continued- statement-offset, and so on. The Emacs Info pages describe these variables in gory detail; however, I find that the default values work quite well, for a number of indentation styles. Unless you have a particularly unique artistic flair when it comes to indenting your code, I suspect that you won't have to fiddle with Emacs' indentation variables.

A line is indented appropriately when you press TAB anywhere on the line. This does not cause a tab character to be inserted; it just indents the line according to the variable values mentioned above. If you want to actually insert a tab character, prefix it with C-q.

To see how this works, start up Emacs and edit a file called foo.c. Type a few lines of bogus C code, pressing RET after each. Then go back and press TAB on each line to see the results.

Pressing LFD instead of RET is equivalent to pressing RET followed by TAB—that is, you start a new line, and it is automatically indented for you. I find it particularly useful to bind RET to this function, which is newline-and-indent, so that I don't have to use LFD when writing code. In my Emacs configuration file, I include the line:

(define-key c-mode-map "\C-m' -newline-and-indent)

One feature that you may have noticed is that closing braces and parentheses automatically blink their opening counterparts. This can help you to check that parentheses are balanced in your code. If you don't like this feature, you can turn it off using

(setq blink-matching-paren nil)

in your .emacs file (or ~/emacs/startup.el, for those of you using the method described last month. Hereafter, we will refer only to .emacs, but keep in mind that all of these customizations can be used with both methods).

If you're running Emacs under X, the paren library will cause matching parentheses and braces to be highlighted whenever point is on an opening brace/parenthesis, or after a closing brace/parenthesis. Simply including

(load-library "paren")

in your .emacs file will enable this feature. Balanced parentheses are highlighted in the region face; you can change the color or font used with commands such as set-face-foreground, set-face-font, and so on.

For example,

(set-face-background -0region "pink")

will set the background color for this face to pink. The region face is also used to display the current region when transient-mark-mode is enabled. We'll talk a bit more about faces below.

You'll also notice that typing a closing brace (on a line by itself) will exdent the line containing the brace. When

typing code such as:

int foo() {
  /* Your code here */

After pressing RET, the next line will be indented relative to the comment above it (assuming, of course, that you have bound RET to newline-and-indent). Now, after typing the closing brace, you'll end up with:

int foo() {
  /* Your code here */
}

Braces are bound to the function electric-c-brace, which inserts the brace, and corrects indentation on the current line. The indentation of braces, and the text enclosed by them, is controlled by the Emacs variables c-brace-offset, c-imaginary-brace-offset, and so on.

In general, your code should follow the indentation style set forth by Emacs. Adding comments is one exception. Many programmers like to set comments out towards the right margin of the display, as in

int floof(struct shoop *s, int i) {
   s->fnum = i;     /* You are not expected
                      to understand this */
   return 0;
}

Now that TAB has lost its natural ability to add whitespace, how can we add such a comment? Emacs provides the M-; command, which begins a comment starting at the column specified by the variable comment-column, which is set to 24 by default. Of course, you can always add comments by typing

/* ... */ by hand.

You can use M-x comment-region to comment out all lines in the current region. (For Emacs neophytes, the region is defined by moving point to a particular location, using C-Space to set the “mark”, and then moving point elsewhere. The region is the block of text between point and mark. There are various other ways to set the region; for example, under X, dragging mouse-1 over a portion of text will define the region.) Likewise, M-C-\ (that's meta-control-backslash) will indent the current region.

C Mode defines several new moving commands as well. M-C-a will move point to the beginning of the current function. Similarly, M-C-e will move point to the end of the current function. Note, however, that the “current function” is denoted by an opening or closing brace in the first column of text. If you use a C indentation style such as

int foo() {
  /* Your code here */
}

Emacs won't be able to find the beginning of the function, as the opening brace is at the end of the line. For these commands to work properly, you should indent your code as so:

int foo()
{
  /* Your code here */
}

To select the region as the text of the current function, you can use M-C-h. This provides a convenient way to manipulate entire functions. For example, the quick key sequence M-C-h, C-w, M-C-e, C-y will move the current function below the following one. Impress your friends!

The keys M-a and M-e can be used to move to the beginning or end of the current C statement (block, semicolon-delimited expression, etc.).

One last important C Mode feature: macro expansion. If you run M-x c-macro-expand, Emacs will run the C preprocessor on the current region and display the results in another buffer. For example, given the following code:

static XtResource resource_list[] = {
  { RES_N_doputimage, RES_C_doputimage,
    XtRBoolean, sizeof(Boolean),
    XtOffset(app_data_ptr,do_putimage),
    XtRImmediate, (XtPointer) FALSE,
  },
};

Selecting this text as the region, and calling c-macro-expand gives us:

static XtResource resource_list[] = {
  { "doPutImage", "DoPutImage",
    ((char*)&XtStrings[1561]), sizeof(Boolean),
    ((Cardinal) (((char *)
    (&(((app_data_ptr)0)->do_putimage))) -
    ((char *) 0))),
    ((char*)&XtStrings[1695]), (XtPointer) 0,
  },
};

This can be useful if you're trying to debug complex macros, or need to know the definition of a given preprocessor symbol.

Many other modes exist for particular languages, such as Perl Mode, Emacs LISP Mode, Prolog Mode, and so on. Most of these modes share the basic features described above. The best way to learn about a new mode is to enter it (with a command such as M-x perl-mode) and use M-x describe-mode to get a rundown on its features.

______________________

Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

Re: Tutorial: Emacs for Programmers

Anonymous's picture

Several small flaws in the article. The local emacs variables need to be at the end of the source. Or at least for Xemacs they do, they didn't work when in the middle of my code.

/* Local Variables: */

/* mode: C */

/* compile-command: "cd ..; make -k" */

/* End: */

The above works for my projects where the source lives 1 directory below the Makefile.

The compile key bindings are missing some backslashes before the C

;; Save and Compile

;; Uses the compile-command variable which can be set in the source

(defun my-save-and-compile ()

(interactive "")

(save-buffer 0)

(compile compile-command)

)

(define-key c-mode-map "C-cC-c" 'my-save-and-compile)

The above uses the compile-command set by the source. If none has been set then make -k is the system default.

Brian Lane(too busy to find my login)

White Paper
Linux Management with Red Hat Satellite: Measuring Business Impact and ROI

Linux has become a key foundation for supporting today's rapidly growing IT environments. Linux is being used to deploy business applications and databases, trading on its reputation as a low-cost operating environment. For many IT organizations, Linux is a mainstay for deploying Web servers and has evolved from handling basic file, print, and utility workloads to running mission-critical applications and databases, physically, virtually, and in the cloud. As Linux grows in importance in terms of value to the business, managing Linux environments to high standards of service quality — availability, security, and performance — becomes an essential requirement for business success.

Learn More

Sponsored by Red Hat

White Paper
Private PaaS for the Agile Enterprise

If you already use virtualized infrastructure, you are well on your way to leveraging the power of the cloud. Virtualization offers the promise of limitless resources, but how do you manage that scalability when your DevOps team doesn’t scale? In today’s hypercompetitive markets, fast results can make a difference between leading the pack vs. obsolescence. Organizations need more benefits from cloud computing than just raw resources. They need agility, flexibility, convenience, ROI, and control.

Stackato private Platform-as-a-Service technology from ActiveState extends your private cloud infrastructure by creating a private PaaS to provide on-demand availability, flexibility, control, and ultimately, faster time-to-market for your enterprise.

Learn More

Sponsored by ActiveState