Tutorial: Emacs for Programmers

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

Emacs-19 provides support for faces, which allow different kinds of text to be displayed in various fonts and/or colors. In last month's tutorial, we described how to configure faces under Emacs; because use of faces is particularly helpful with respect to editing source code, it bears repeating here.

The command M-x list-faces-display will display the current faces, and their associated names, in another window. Faces are given names such as bold, bold-italic, and so on. These names don't necessarily have anything to do with how the faces appear—for example, your bold face needn't be in a bold font.

The functions set-face-foreground and set-face-background can be used to set the foreground and background colors for a face, respectively. set-face-font sets the font used for a particular face; set-face-underline-p specifies whether a particular face is displayed with an underline.

Faces are used most commonly within Font Lock Mode, a minor mode which causes the current buffer to be “fontified”--that is, the text is displayed in various faces depending on context. For example, when using Font Lock Mode with C Mode, function names are displayed in one face, comments in another, preprocessor directives in another, and so on. This is a pleasant visual effect when editing source code; you can easily identify function names and comments by glancing at the display.

The following function can be used in your Emacs startup file to enable Font Lock Mode and to set the colors for various faces.

defun my-turn-on-font-lock ()
  (interactive "")
  ;;; Color the faces appropriately
  (set-face-foreground -bold "lightblue")
  (set-face-foreground -bold-italic "olivedrab2")
  (set-face-foreground -italic "lightsteelblue")
  (set-face-foreground -modeline "white")
  (set-face-background -modeline "black")
  (set-face-background -highlight "blue")
  ;; Turn off underline property for bold and underline
  (set-face-underline-p -bold nil)
  (set-face-underline-p -underline nil)
  (transient-mark-mode 1)
  (font-lock-mode 1))

Note that in addition to turning on font-lock-mode, I enable transient-mark-mode. In this mode, the current region is shaded using the region face. This can save you a great deal of time trying to remember where the current mark is set.

The above function is called by:

(defun my-window-setup-hook ()
   (set-foreground-color "white")
   (set-background-color "dimgray")
   (set-mouse-color "orchid")
   (set-cursor-color "red")
   (my-turn-on-font-lock))
(add-hook 'window-setup-hook 'my-window-setup-hook)

That is, the Emacs window-setup-hook (which is executed at startup time) calls my-window-setup-hook, which first sets the foreground and background colors for the window, and then enables Font Lock Mode.

You must enable Font Lock Mode separately for each buffer that you wish to use it in. For this reason, I have Emacs call my-turn-on-font-lock whenever I enter C Mode, Emacs LISP Mode, or Perl Mode:

(add-hook 'c-mode-hook 'my-turn-on-font-lock)
(add-hook 'emacs-lisp-mode-hook 'my-turn-on-font-lock)
(add-hook 'perl-mode-hook 'my-turn-on-font-lock)

The best way to determine how to configure faces to your liking is to experiment with the code given above. There are several variables which control which faces Font Lock Mode uses for particular kinds of code. For example, font-lock-comment-face is the face used for comments. By default, its value is italic, which we set above to use the foreground color of lightsteelblue. You can either set the face properties for bold, italic, and so on directly, or you can operate on font-lock-comment-face, font-lock-function-name-face, et cetera. Using M-x apropos and entering font-lock will give you a list of functions and variables associated with Font Lock Mode.

Using tags

Emacs has a number of features dealing with tags, which are simply marked locations in your source code. The most common use of tags is to mark the beginning of a function definition. You can then jump directly to that function definition, no matter what source file it lives in.

To handle tags, Emacs uses a tags file, which is (by default) named TAGS in the directory where your source files live. Before experimenting with tags, let's create a tags file. From the shell prompt, use the command

etags filenames...

where filenames are the names of the source files in the current directory. For example,

etags *.c *.h

This will create the file TAGS, based on the C source and header files in the current directory.

Let's say that we have three source files: grover.c, oscar.c, and telly.c. These files might contain code such as:

/* grover.c ********************/
int grover() {
  /* Code for grover... */
}
/* oscar.c *********************/
int oscar() {
  /* Code for oscar... */
}
/* telly.c *********************/
int telly_monster() {
  /* Code for telly_monster... */
}
int main(int argc, char *argv[]) {
  /* Code for main... */
}

Running etags on these three source files will create tags for each function in the three files. (Using etags with the -t option will also include any typdefs found in the source.)

Now, we can use commands such as M-. (that's meta-dot) which will find a given tag. When we press M-. while editing one of these source files, Emacs will ask us:

Find tag: (default oscar)

You can enter the name of a tag (function name), such as telly_monster, and the source file containing that tag will automatically be opened, and point set to the line containing the tag. This is a very quick way to move between source files when editing.

The default tag for M-. is set based on whatever word point is currently on. Therefore, if point is currently over a call to the function oscar(), pressing M-. followed by RET will take us directly to the definition of oscar().

M-x find-tag-regexp will find the tag matched by the given regular expression. Therefore, using find-tag-regexp and giving a portion of the function name will take you to that function (assuming that the regular expression that you specified was unique for that function). If you have a set of similarly-named functions, using M-0 M-. (that's meta-zero meta-dot) will take you to the next tag matched by the previous use of find-tag-regexp.

Similarly, you can use M-x tags-search, which will search for the named regular expression in any of the files named in the current TAGS file. That is, tags-search does not limit its search for tags-it will search for any text in the files listed in TAGS. You can use M-, to search for the next instance of the given regular expression.

Another useful feature is tags completion. Pressing M-TAB will attempt to complete the current word based on functions listed in the current tags file. Therefore, when calling the function telly_monster, we can type tel M-TAB which will complete the name for us. If a given word has more than one completion, a *Completions* buffer will be opened, listing all possible choices. Under X, pressing mouse-2 on a completion will select it.

There is one caveat associated with using tags—you will occasionally need to refresh the TAGS file, in case you have done major reorganization of your code. Emacs doesn't depend on the TAGS file being 100% accurate—it will search for a tag if it is not found in the exact location given in the file. However, if you mangle your code considerably, re-run etags to refresh the tags database.

Also note that Emacs can use more than one TAGS file at a time. Most tags-based functions assume use of the file TAGS in the current directory. If you are editing source files spread across several directories, M-x visit-tags-table can be used to load another TAGS file into Emacs' list of known tags. Alternately, you can set the variable tags-table-list to a list of files or directories where TAGS files can be found. For example, I might want Emacs to always know about tags found in common library routines. In my Emacs startup file, I would use something like:

(setq tags-table-list '("~/lib" "~/src/lib" "~/common"))

The TAGS files found in the named directories would be used in addition to TAGS in the current directory.

______________________

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