prev UP NEXT GNU Emacs Lisp Reference Manual

36.1: Writing Clean Lisp Programs

Here are some tips for avoiding common errors in writing Lisp code intended for widespread use:

  • Since all global variables share the same name space, and all functions share another name space, you should choose a short word to distinguish your program from other Lisp programs. Then take care to begin the names of all global variables, constants, and functions with the chosen prefix. This helps avoid name conflicts.

    This recommendation applies even to names for traditional Lisp primitives that are not primitives in Emacs Lisp---even to cadr. Believe it or not, there is more than one plausible way to define cadr. Play it safe; append your name prefix to produce a name like foo-cadr or mylib-cadr instead.

    If you write a function that you think ought to be added to Emacs under a certain name, such as twiddle-files, don't call it by that name in your program. Call it mylib-twiddle-files in your program, and send mail to `bug-gnu-emacs@prep.ai.mit.edu' suggesting we add it to Emacs. If and when we do, we can change the name easily enough.

    If one prefix is insufficient, your package may use two or three alternative common prefixes, so long as they make sense.

    Separate the prefix from the rest of the symbol name with a hyphen, `-'. This will be consistent with Emacs itself and with most Emacs Lisp programs.

  • It is often useful to put a call to provide in each separate library program, at least if there is more than one entry point to the program.
  • If a file requires certain other library programs to be loaded beforehand, then the comments at the beginning of the file should say so. Also, use require to make sure they are loaded.
  • If one file foo uses a macro defined in another file bar, foo should contain this expression before the first use of the macro:
    (eval-when-compile (require 'bar))
    

    (And bar should contain (provide 'bar), to make the require work.) This will cause bar to be loaded when you byte-compile foo. Otherwise, you risk compiling foo without the necessary macro loaded, and that would produce compiled code that won't work right. See Compiling Macros.

    Using eval-when-compile avoids loading bar when the compiled version of foo is used.

  • If you define a major mode, make sure to run a hook variable using run-hooks, just as the existing major modes do. See Hooks.
  • If the purpose of a function is to tell you whether a certain condition is true or false, give the function a name that ends in `p'. If the name is one word, add just `p'; if the name is multiple words, add `-p'. Examples are framep and frame-live-p.
  • If a user option variable records a true-or-false condition, give it a name that ends in `-flag'.
  • Please do not define C-c letter as a key in your major modes. These sequences are reserved for users; they are the only sequences reserved for users, so we cannot do without them.

    Instead, define sequences consisting of C-c followed by a non-letter. These sequences are reserved for major modes.

    Changing all the major modes in Emacs 18 so they would follow this convention was a lot of work. Abandoning this convention would make that work go to waste, and inconvenience users.

  • Sequences consisting of C-c followed by {, }, <, >, : or ; are also reserved for major modes.
  • Sequences consisting of C-c followed by any other punctuation character are allocated for minor modes. Using them in a major mode is not absolutely prohibited, but if you do that, the major mode binding may be shadowed from time to time by minor modes.
  • You should not bind C-h following any prefix character (including C-c). If you don't bind C-h, it is automatically available as a help character for listing the subcommands of the prefix character.
  • You should not bind a key sequence ending in ESC except following another ESC. (That is, it is ok to bind a sequence ending in ESC ESC.)

    The reason for this rule is that a non-prefix binding for ESC in any context prevents recognition of escape sequences as function keys in that context.

  • Applications should not bind mouse events based on button 1 with the shift key held down. These events include S-mouse-1, M-S-mouse-1, C-S-mouse-1, and so on. They are reserved for users.
  • Modes should redefine mouse-2 as a command to follow some sort of reference in the text of a buffer, if users usually would not want to alter the text in that buffer by hand. Modes such as Dired, Info, Compilation, and Occur redefine it in this way.
  • When a package provides a modification of ordinary Emacs behavior, it is good to include a command to enable and disable the feature, Provide a command named whatever-mode which turns the feature on or off, and make it autoload (see Autoload). Design the package so that simply loading it has no visible effect---that should not enable the feature. Users will request the feature by invoking the command.
  • It is a bad idea to define aliases for the Emacs primitives. Use the standard names instead.
  • Redefining an Emacs primitive is an even worse idea. It may do the right thing for a particular program, but there is no telling what other programs might break as a result.
  • If a file does replace any of the functions or library programs of standard Emacs, prominent comments at the beginning of the file should say which functions are replaced, and how the behavior of the replacements differs from that of the originals.
  • Please keep the names of your Emacs Lisp source files to 13 characters or less. This way, if the files are compiled, the compiled files' names will be 14 characters or less, which is short enough to fit on all kinds of Unix systems.
  • Don't use next-line or previous-line in programs; nearly always, forward-line is more convenient as well as more predictable and robust. See Text Lines.
  • Don't call functions that set the mark, unless setting the mark is one of the intended features of your program. The mark is a user-level feature, so it is incorrect to change the mark except to supply a value for the user's benefit. See The Mark.

    In particular, don't use these functions:

    • beginning-of-buffer, end-of-buffer
    • replace-string, replace-regexp

    If you just want to move point, or replace a certain string, without any of the other features intended for interactive users, you can replace these functions with one or two lines of simple Lisp code.

  • Use lists rather than vectors, except when there is a particular reason to use a vector. Lisp has more facilities for manipulating lists than for vectors, and working with lists is usually more convenient.

    Vectors are advantageous for tables that are substantial in size and are accessed in random order (not searched front to back), provided there is no need to insert or delete elements (only lists allow that).

  • The recommended way to print a message in the echo area is with the message function, not princ. See The Echo Area.
  • When you encounter an error condition, call the function error (or signal). The function error does not return. See Signaling Errors.

    Do not use message, throw, sleep-for, or beep to report errors.

  • An error message should start with a capital letter but should not end with a period.
  • Try to avoid using recursive edits. Instead, do what the Rmail e command does: use a new local keymap that contains one command defined to switch back to the old local keymap. Or do what the edit-options command does: switch to another buffer and let the user switch back at will. See Recursive Editing.
  • In some other systems there is a convention of choosing variable names that begin and end with `*'. We don't use that convention in Emacs Lisp, so please don't use it in your programs. (Emacs uses such names only for program-generated buffers.) The users will find Emacs more coherent if all libraries use the same conventions.
  • Indent each function with C-M-q (indent-sexp) using the default indentation parameters.
  • Don't make a habit of putting close-parentheses on lines by themselves; Lisp programmers find this disconcerting. Once in a while, when there is a sequence of many consecutive close-parentheses, it may make sense to split them in one or two significant places.
  • Please put a copyright notice on the file if you give copies to anyone. Use the same lines that appear at the top of the Lisp files in Emacs itself. If you have not signed papers to assign the copyright to the Foundation, then place your name in the copyright notice in place of the Foundation's name.