(lispref.info)Example Major Modes


Next: Auto Major Mode Prev: Major Mode Conventions Up: Major Modes

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 mode line.
       (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)
       (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 if he or she so wishes.

     (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 Emacs.
     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 mode line.
       (lisp-mode-variables nil)              ; This define various variables.
       (run-hooks 'emacs-lisp-mode-hook))     ; This permits the user to use a
                                              ;   hook to customize the mode.


automatically generated by info2www