[ < ] [ > ]   [ << ] [Plus haut] [ >> ]         [Top] [Table des matières] [Index] [ ? ]

23.2.8 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 the syntax table for this mode.
(defvar text-mode-syntax-table
  (let ((st (make-syntax-table)))
    (modify-syntax-entry ?\" ".   " st)
    (modify-syntax-entry ?\\ ".   " st)
    ;; Add `p' so M-c on `hello' leads to `Hello', not `hello'.
    (modify-syntax-entry ?' "w p" st)
    st)
  "Syntax table used while in `text-mode'.")

;; Create the keymap for this mode.
(defvar text-mode-map
  (let ((map (make-sparse-keymap)))
    (define-key map "\e\t" 'ispell-complete-word)
    (define-key map "\es" 'center-line)
    (define-key map "\eS" 'center-paragraph)
    map)
  "Keymap for `text-mode'.
Many other modes, such as Mail mode, Outline mode
and Indented Text mode, inherit all the commands
defined in this map.")

Here is how the actual mode command is defined now:

 
(define-derived-mode text-mode nil "Text"
  "Major mode for editing text written for humans to read.
In this mode, paragraphs are delimited only by blank or white lines.
You can thus get the full benefit of adaptive filling
 (see the variable `adaptive-fill-mode').
\\{text-mode-map}
Turning on Text mode runs the normal hook `text-mode-hook'."
  (make-local-variable 'text-mode-variant)
  (setq text-mode-variant t)
  ;; These two lines are a feature added recently.
  (set (make-local-variable 'require-final-newline)
       mode-require-final-newline)
  (set (make-local-variable 'indent-line-function) 'indent-relative))

(The last line is redundant nowadays, since indent-relative is the default value, and we'll delete it in a future version.)

Here is how it was defined formerly, before define-derived-mode existed:

 
;; This isn't needed nowadays, since define-derived-mode does it.
(defvar text-mode-abbrev-table nil
  "Abbrev table used while in text mode.")
(define-abbrev-table 'text-mode-abbrev-table ())

(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)
  (setq local-abbrev-table text-mode-abbrev-table)
  (set-syntax-table text-mode-syntax-table)
  ;; These four lines are absent from the current version
  ;; not because this is done some other way, but rather
  ;; because nowadays Text mode uses the normal definition of paragraphs.
  (make-local-variable 'paragraph-start)
  (setq paragraph-start (concat "[ \t]*$\\|" page-delimiter))
  (make-local-variable 'paragraph-separate)
  (setq paragraph-separate paragraph-start)
  (make-local-variable 'indent-line-function)
  (setq indent-line-function 'indent-relative-maybe)
  (setq mode-name "Text")
  (setq major-mode 'text-mode)
  (run-mode-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 lisp-mode-abbrev-table nil "")

(defvar emacs-lisp-mode-syntax-table
  (let ((table (make-syntax-table)))
    (let ((i 0))

      ;; Set syntax of chars up to ‘0’ to say they are
      ;;   part of symbol names but not words.
      ;;   (The digit ‘0’ is 48 in the ASCII character set.)
      (while (< i ?0)
	(modify-syntax-entry i "_   " table)
	(setq i (1+ i)))
      ;; … similar code follows for other character ranges.
      ;; Then set the syntax codes for characters that are special in Lisp.
      (modify-syntax-entry ?  "    " table)
      (modify-syntax-entry ?\t "    " table)
      (modify-syntax-entry ?\f "    " table)
      (modify-syntax-entry ?\n ">   " table)
      ;; Give CR the same syntax as newline, for selective-display.
      (modify-syntax-entry ?\^m ">   " table)
      (modify-syntax-entry ?\; "<   " table)
      (modify-syntax-entry ?` "'   " table)
      (modify-syntax-entry ?' "'   " table)
      (modify-syntax-entry ?, "'   " table)
      ;; …likewise for many other characters…
      (modify-syntax-entry ?\( "()  " table)
      (modify-syntax-entry ?\) ")(  " table)
      (modify-syntax-entry ?\[ "(]  " table)
      (modify-syntax-entry ?\] ")[  " table))
    table))
;; Create an abbrev table for lisp-mode.
(define-abbrev-table 'lisp-mode-abbrev-table ())

The three modes for Lisp share much of their code. For instance, each calls the following function to set various variables:

 
(defun lisp-mode-variables (lisp-syntax)
  (when lisp-syntax
    (set-syntax-table lisp-mode-syntax-table))
  (setq local-abbrev-table lisp-mode-abbrev-table)
  …

In Lisp and most programming languages, we want the paragraph commands to treat only blank lines as paragraph separators. And the modes should undestand the Lisp conventions for comments. The rest of lisp-mode-variables sets this up:

 
  (make-local-variable 'paragraph-start)
  (setq paragraph-start (concat page-delimiter "\\|$" ))
  (make-local-variable 'paragraph-separate)
  (setq paragraph-separate paragraph-start)
  …
  (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-z to run-lisp, but the other Lisp modes do not. However, all Lisp modes have some commands in common. The following code sets up the common commands:

 
(defvar shared-lisp-mode-map ()
  "Keymap for commands shared by all sorts of Lisp modes.")

;; Putting this if after the defvar is an older style.
(if shared-lisp-mode-map
    ()
   (setq shared-lisp-mode-map (make-sparse-keymap))
   (define-key shared-lisp-mode-map "\e\C-q" 'indent-sexp)
   (define-key shared-lisp-mode-map "\177"
               'backward-delete-char-untabify))

And here is the code to set up the keymap for Lisp mode:

 
(defvar lisp-mode-map ()
  "Keymap for ordinary Lisp mode...")

(if lisp-mode-map
    ()
  (setq lisp-mode-map (make-sparse-keymap))
  (set-keymap-parent lisp-mode-map shared-lisp-mode-map)
  (define-key lisp-mode-map "\e\C-x" 'lisp-eval-defun)
  (define-key lisp-mode-map "\C-c\C-z" 'run-lisp))

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

 
(defun lisp-mode ()
  "Major mode for editing Lisp code for Lisps other than GNU Emacs Lisp.
Commands:
Delete converts tabs to spaces as it moves back.
Blank lines separate paragraphs.  Semicolons start comments.
\\{lisp-mode-map}
Note that `run-lisp' may be used either to start an inferior Lisp job
or to switch back to an existing one.

Entry to this mode calls the value of `lisp-mode-hook'
if that value is non-nil."
  (interactive)
  (kill-all-local-variables)
  (use-local-map lisp-mode-map)          ; Select the mode's keymap.
  (setq major-mode 'lisp-mode)           ; This is how describe-mode
                                         ;   finds out what to describe.
  (setq mode-name "Lisp")                ; This goes into the mode line.
  (lisp-mode-variables t)                ; This defines various variables.
  (make-local-variable 'comment-start-skip)
  (setq comment-start-skip
        "\\(\\(^\\|[^\\\\\n]\\)\\(\\\\\\\\\\)*\\)\\(;+\\|#|\\) *")
  (make-local-variable 'font-lock-keywords-case-fold-search)
  (setq font-lock-keywords-case-fold-search t)
  (setq imenu-case-fold-search t)
  (set-syntax-table lisp-mode-syntax-table)
  (run-mode-hooks 'lisp-mode-hook))      ; This permits the user to use a
                                         ;   hook to customize the mode.

[ < ] [ > ]   [ << ] [Plus haut] [ >> ]         [Top] [Table des matières] [Index] [ ? ]

Ce document a été généré par Eric Reinbold le 13 Octobre 2007 en utilisant texi2html 1.78.