June 21, 2006

Emacs tips: More fun with outlines

Author: JT Smith

In this article I'll show how to export and print outlines, customize outline heading line colors, and use outline mode's special features in everyday documents -- such as numbered lists, traditional outlines with Roman numerals, and even book manuscripts containing chapter and section headings.

Using structured documents

You're not stuck with asterisks as the only way to delimit headings. By default, page breaks are also valid delimiters, which comes in handy when you're working on paginated files -- if you turn on outline mode in such a file, each page becomes a major heading in the outline itself. Use the outline movement commands to move from page to page in the document and to hide pages. Page breaks are Ctrl-l characters; to insert one in a document, type Ctrl-q Ctrl-l. This will show up in your document as ^L.

Multiple page break characters also count as subheadings -- for instance, two page break characters together, ^L^L, make a valid second-level heading, but I haven't yet heard of a good real-world use for this.

You can customize the outline delimiters by setting the value for outline-regexp to the new value, a regular expression that matches all possible heading line delimiters.

The heading level is determined by the length of the match -- the shortest possible match is the first heading, the second-shortest is the second heading, and so on. So usually outline-regexp will be a long regexp with all of the delimiters separated by alternation operators (\|). But it's not always easy to do -- you have to determine the right pattern so that the first delimiter contains the least number of characters matched, the second contains the second-least, and so on all the way through.

For example, suppose you have a file that contains a book manuscript. Chapters in this file always begin with a numbered title line, sections beneath it are titled with the chapter number followed by a period and section number, and subsections add another number, like so:

  1. The beginning

  1.1	Some details

  1.2	More details

  2. The middle

  2.1	Things you should know

  2.1.1		Like this

  2.1.2		And this

  2.2	The crux of the matter

  3. The end

  3.1	Wrapping it up

  3.2	The finish line

  3.2.1		This is it

  3.2.2		Seriously

You can view such a file as an outline in outline mode by changing the outline-regexp variable to a regexp that will match one or more numbers followed by the grouping of a period character and an optional second number. One way to test the regexp is to evaluate it right in the buffer, by typing:

Esc-x eval-expression (setq outline-regexp "[0-9]+\\(\\.[0-9]+\\)*")

After you do that, typing Ctrl-c Ctrl-q in the buffer will make it look like the following:

  1. The beginning...

  2. The middle...

  3. The end...

To make this custom regexp work automagically every time that particular file is opened in a buffer, add the following Emacs variable declarations to the very end of the file:

Local Variables:
mode: outline
outline-regexp: "[0-9]+\\(\\.[0-9]+\\)*"
End: ***

People use these techniques for all kinds of special applications. In the Emacs wiki outline mode documentation, there's a method described for using it with Wikipedia articles, as well as a way to use Roman numerals as headings.

This regexp is a variation on the Roman numerals:

" *\\([IVXMC]+\\|[A-Za-z0-9]+\\)\\. *"

This works on buffers containing outlines written in a traditional format, with headings space-indented and aligned, such as this:

  I. Heading
     A. Subheading
        1. Point
        2. Point
        3. Point
           a. details
           b. details
           c. details
     B. Subheading
     C. Subheading
 II. Heading
III. Heading
 IV. Heading

Various hackers have written Elisp files that contain customizations for outline mode, including outline-regexps that you can use with HTML files, LaTeX files, and presentation slides.

Outline colors

If font lock (a minor mode) is turned on (use Esc-x font-lock-mode), the outline mode heading lines are displayed in color. To customize the outline mode colors, you'll want to change the values used for the font lock faces. The following list shows the names of the faces used for the various levels of heading lines:

  1. font-lock-function-name-face
  2. font-lock-variable-name-face
  3. font-lock-keyword-face
  4. font-lock-builtin-face
  5. font-lock-comment-face
  6. font-lock-constant-face
  7. font-lock-type-face
  8. font-lock-string-face

After the eighth heading level, the value for font-lock-function-name-face is used for all subsequent levels.

To customize the faces, type Esc-x customize-face and select the colors for the font lock faces from the menus that appear.

Printing and extracting outlines

Outline mode alters the view of the file in Emacs without changing the contents of the file itself. But what happens if you want to use an outline outside of Emacs -- for instance, if you want to print it?

GNU Enscript has a highlighting filter, outline, that processes files written for outline mode and sets heading lines in bold. Specify it with the -E option. For example, to preview a PostScript version of your file in gv, type:

enscript -Eoutline -o - myfile | gv -

And it's easy enough to extract the outline headers with grep. Just grep for the heading lines, which in the default case are those that begin with one or more asterisks:

grep '^\*' myfile > outline

To do the same with a file containing numbered chapters and
sections, search for lines beginning with a number of any length
followed by a period character:

grep '^[0-9]+\.' myfile > outline

To do the same with a traditional-format outline:

grep '^[ ]*\([IVXMC]\+\|[A-Za-z0-9]\+\)\.' myfile > outline

If you have a title or other important text at the beginning of the outline, first use head to get those lines, and then use grep as just described to extract the heading lines. For example, to write the first four lines plus all heading lines of myfile to the file myfile.outline, type:

head -n 4 myfile > myfile.outline; grep '^\*' myfile >> myfile.outline

Minor mode and other tools

These two articles have described the use of outline mode, a major mode. But all the same outline commands are available as a minor mode (Outline-minor-mode), so you can use it in buffers in conjunction with some other major mode. That way you can use all the Emacs outline commands, but keep the functionality of the other major mode for the buffer that you're working on. This is handy for when you're working on program source code (say, in Perl mode).

But there are also some drawbacks. Outline minor mode gives almost the same functionality as outline mode, except the heading lines are not displayed in color, and instead of Ctrl-c as a default prefix to commands, you have to type Ctrl-c @ -- so for the command to hide sublevels as shown above, you'd type Ctrl-c @ Ctrl-q. This isn't as quick as the regular outline mode commands.

There are many other outline tools and extensions to the vanilla outline mode. Carsten Dominik's outline-magic Elisp, for example, contains a few extensions to outline mode. And Emacs itself includes other modes and tools for making and using outlines. The Emacs wiki has a good listing of them, and a page on Allout, another outlining mode which is included in both GNU Emacs and XEmacs. One developer has even written a package that lets you use Allout in Vim.

Click Here!