Next: , Previous: , Up: Major Modes   [Contents][Index]


33.1.2 Major Mode Examples

Text mode is perhaps the simplest mode besides Fundamental mode. Here are excerpts from text-mode.el that illustrate many of the conventions listed above:

;; Create mode-specific tables.
(defvar text-mode-syntax-table nil
  "Syntax table used while in text mode.")
(if text-mode-syntax-table
    ()              ; Do not change the table if it is already set up.
  (setq text-mode-syntax-table (make-syntax-table))
  (modify-syntax-entry ?\" ".   " text-mode-syntax-table)
  (modify-syntax-entry ?\\ ".   " text-mode-syntax-table)
  (modify-syntax-entry ?' "w   " text-mode-syntax-table))
(defvar text-mode-abbrev-table nil
  "Abbrev table used while in text mode.")
(define-abbrev-table 'text-mode-abbrev-table ())
(defvar text-mode-map nil)   ; Create a mode-specific keymap.

(if text-mode-map
    ()              ; Do not change the keymap if it is already set up.
  (setq text-mode-map (make-sparse-keymap))
  (define-key text-mode-map "\t" 'tab-to-tab-stop)
  (define-key text-mode-map "\es" 'center-line)
  (define-key text-mode-map "\eS" 'center-paragraph))

Here is the complete major mode function definition for Text mode:

(defun text-mode ()
  "Major mode for editing text intended for humans to read.
 Special commands: \\{text-mode-map}
Turning on text-mode runs the hook `text-mode-hook'."
  (interactive)
  (kill-all-local-variables)
  (use-local-map text-mode-map)     ; This provides the local keymap.
  (setq mode-name "Text")           ; This name goes into the modeline.
  (setq major-mode 'text-mode)      ; This is how describe-mode
                                    ;   finds the doc string to print.
  (setq local-abbrev-table text-mode-abbrev-table)
  (set-syntax-table text-mode-syntax-table)
  (run-hooks 'text-mode-hook))      ; Finally, this permits the user to
                                    ;   customize the mode with a hook.

The three Lisp modes (Lisp mode, Emacs Lisp mode, and Lisp Interaction mode) have more features than Text mode and the code is correspondingly more complicated. Here are excerpts from lisp-mode.el that illustrate how these modes are written.

;; Create mode-specific table variables.
(defvar lisp-mode-syntax-table nil "")
(defvar emacs-lisp-mode-syntax-table nil "")
(defvar lisp-mode-abbrev-table nil "")
(if (not emacs-lisp-mode-syntax-table) ; Do not change the table
                                       ;   if it is already set.
    (let ((i 0))
      (setq emacs-lisp-mode-syntax-table (make-syntax-table))
      ;; Set syntax of chars up to 0 to class of chars that are
      ;;   part of symbol names but not words.
      ;;   (The number 0 is 48 in the ASCII character set.)
      (while (< i ?0)
        (modify-syntax-entry i "_   " emacs-lisp-mode-syntax-table)
        (setq i (1+ i)))
      …
      ;; Set the syntax for other characters.
      (modify-syntax-entry ?  "    " emacs-lisp-mode-syntax-table)
      (modify-syntax-entry ?\t "    " emacs-lisp-mode-syntax-table)
      …
      (modify-syntax-entry ?\( "()  " emacs-lisp-mode-syntax-table)
      (modify-syntax-entry ?\) ")(  " emacs-lisp-mode-syntax-table)
      …))
;; Create an abbrev table for lisp-mode.
(define-abbrev-table 'lisp-mode-abbrev-table ())

Much code is shared among the three Lisp modes. The following function sets various variables; it is called by each of the major Lisp mode functions:

(defun lisp-mode-variables (lisp-syntax)
  ;; The lisp-syntax argument is nil in Emacs Lisp mode,
  ;;   and t in the other two Lisp modes.
  (cond (lisp-syntax
         (if (not lisp-mode-syntax-table)
             ;; The Emacs Lisp mode syntax table always exists, but
             ;;   the Lisp Mode syntax table is created the first time a
             ;;   mode that needs it is called.  This is to save space.
             (progn (setq lisp-mode-syntax-table
                       (copy-syntax-table emacs-lisp-mode-syntax-table))
                    ;; Change some entries for Lisp mode.
                    (modify-syntax-entry ?\| "\"   "
                                         lisp-mode-syntax-table)
                    (modify-syntax-entry ?\[ "_   "
                                         lisp-mode-syntax-table)
                    (modify-syntax-entry ?\] "_   "
                                         lisp-mode-syntax-table)))
          (set-syntax-table lisp-mode-syntax-table)))
  (setq local-abbrev-table lisp-mode-abbrev-table)
  …)

Functions such as forward-paragraph use the value of the paragraph-start variable. Since Lisp code is different from ordinary text, the paragraph-start variable needs to be set specially to handle Lisp. Also, comments are indented in a special fashion in Lisp and the Lisp modes need their own mode-specific comment-indent-function. The code to set these variables is the rest of lisp-mode-variables.

  (make-local-variable 'paragraph-start)
  ;; Having ‘^’ is not clean, but page-delimiter
  ;; has them too, and removing those is a pain.
  (setq paragraph-start (concat "^$\\|" page-delimiter))
  …
  (make-local-variable 'comment-indent-function)
  (setq comment-indent-function 'lisp-comment-indent))

Each of the different Lisp modes has a slightly different keymap. For example, Lisp mode binds C-c C-l to run-lisp, but the other Lisp modes do not. However, all Lisp modes have some commands in common. The following function adds these common commands to a given keymap.

(defun lisp-mode-commands (map)
  (define-key map "\e\C-q" 'indent-sexp)
  (define-key map "\177" 'backward-delete-char-untabify)
  (define-key map "\t" 'lisp-indent-line))

Here is an example of using lisp-mode-commands to initialize a keymap, as part of the code for Emacs Lisp mode. First we declare a variable with defvar to hold the mode-specific keymap. When this defvar executes, it sets the variable to nil if it was void. Then we set up the keymap if the variable is nil.

This code avoids changing the keymap or the variable if it is already set up. This lets the user customize the keymap.

(defvar emacs-lisp-mode-map () "")
(if emacs-lisp-mode-map
    ()
  (setq emacs-lisp-mode-map (make-sparse-keymap))
  (define-key emacs-lisp-mode-map "\e\C-x" 'eval-defun)
  (lisp-mode-commands emacs-lisp-mode-map))

Finally, here is the complete major mode function definition for Emacs Lisp mode.

(defun emacs-lisp-mode ()
  "Major mode for editing Lisp code to run in SXEmacs.
Commands:
Delete converts tabs to spaces as it moves back.
Blank lines separate paragraphs.  Semicolons start comments.
\\{emacs-lisp-mode-map}
Entry to this mode runs the hook `emacs-lisp-mode-hook'."
  (interactive)
  (kill-all-local-variables)
  (use-local-map emacs-lisp-mode-map)    ; This provides the local keymap.
  (set-syntax-table emacs-lisp-mode-syntax-table)
  (setq major-mode 'emacs-lisp-mode)     ; This is how describe-mode
                                         ;   finds out what to describe.
  (setq mode-name "Emacs-Lisp")          ; This goes into the modeline.
  (lisp-mode-variables nil)              ; This defines various variables.
  (run-hooks 'emacs-lisp-mode-hook))     ; This permits the user to use a
                                         ;   hook to customize the mode.

Next: , Previous: , Up: Major Modes   [Contents][Index]