-@node Example Major Modes
-@subsection Major Mode Examples
-
- Text mode is perhaps the simplest mode besides Fundamental mode.
-Here are excerpts from @file{text-mode.el} that illustrate many of
-the conventions listed above:
-
-@smallexample
-@group
-;; @r{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'.")
-@end group
-
-;; @r{Create the keymap for this mode.}
-@group
-(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.")
-@end group
-@end smallexample
-
- Here is how the actual mode command is defined now:
-
-@smallexample
-@group
-(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'."
-@end group
-@group
- (make-local-variable 'text-mode-variant)
- (setq text-mode-variant t)
- ;; @r{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))
-@end group
-@end smallexample
-
- But here is how it was defined formerly, before
-@code{define-derived-mode} existed:
-
-@smallexample
-@group
-;; @r{This isn't needed nowadays, since @code{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 ())
-@end group
-
-@group
-(defun text-mode ()
- "Major mode for editing text intended for humans to read...
- Special commands: \\@{text-mode-map@}
-@end group
-@group
-Turning on text-mode runs the hook `text-mode-hook'."
- (interactive)
- (kill-all-local-variables)
- (use-local-map text-mode-map)
-@end group
-@group
- (setq local-abbrev-table text-mode-abbrev-table)
- (set-syntax-table text-mode-syntax-table)
-@end group
-@group
- ;; @r{These four lines are absent from the current version}
- ;; @r{not because this is done some other way, but rather}
- ;; @r{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)
-@end group
-@group
- (setq mode-name "Text")
- (setq major-mode 'text-mode)
- (run-mode-hooks 'text-mode-hook)) ; @r{Finally, this permits the user to}
- ; @r{customize the mode with a hook.}
-@end group
-@end smallexample
-
-@cindex @file{lisp-mode.el}
- 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
-@file{lisp-mode.el} that illustrate how these modes are written.
-
-@cindex syntax table example
-@smallexample
-@group
-;; @r{Create mode-specific table variables.}
-(defvar lisp-mode-syntax-table nil "")
-(defvar lisp-mode-abbrev-table nil "")
-@end group
-
-@group
-(defvar emacs-lisp-mode-syntax-table
- (let ((table (make-syntax-table)))
- (let ((i 0))
-@end group
-
-@group
- ;; @r{Set syntax of chars up to @samp{0} to say they are}
- ;; @r{part of symbol names but not words.}
- ;; @r{(The digit @samp{0} is @code{48} in the @acronym{ASCII} character set.)}
- (while (< i ?0)
- (modify-syntax-entry i "_ " table)
- (setq i (1+ i)))
- ;; @r{@dots{} similar code follows for other character ranges.}
-@end group
-@group
- ;; @r{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)
-@end group
-@group
- ;; @r{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)
-@end group
-@group
- ;; @r{@dots{}likewise for many other characters@dots{}}
- (modify-syntax-entry ?\( "() " table)
- (modify-syntax-entry ?\) ")( " table)
- (modify-syntax-entry ?\[ "(] " table)
- (modify-syntax-entry ?\] ")[ " table))
- table))
-@end group
-@group
-;; @r{Create an abbrev table for lisp-mode.}
-(define-abbrev-table 'lisp-mode-abbrev-table ())
-@end group
-@end smallexample
-
- 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:
-
-@smallexample
-@group
-(defun lisp-mode-variables (lisp-syntax)
- (when lisp-syntax
- (set-syntax-table lisp-mode-syntax-table))
- (setq local-abbrev-table lisp-mode-abbrev-table)
- @dots{}
-@end group
-@end smallexample
-
- Functions such as @code{forward-paragraph} use the value of the
-@code{paragraph-start} variable. Since Lisp code is different from
-ordinary text, the @code{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
-@code{comment-indent-function}. The code to set these variables is the
-rest of @code{lisp-mode-variables}.
-
-@smallexample
-@group
- (make-local-variable 'paragraph-start)
- (setq paragraph-start (concat page-delimiter "\\|$" ))
- (make-local-variable 'paragraph-separate)
- (setq paragraph-separate paragraph-start)
- @dots{}
-@end group
-@group
- (make-local-variable 'comment-indent-function)
- (setq comment-indent-function 'lisp-comment-indent))
- @dots{}
-@end group
-@end smallexample
-
- Each of the different Lisp modes has a slightly different keymap. For
-example, Lisp mode binds @kbd{C-c C-z} to @code{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:
-
-@smallexample
-@group
-(defvar shared-lisp-mode-map ()
- "Keymap for commands shared by all sorts of Lisp modes.")
-
-;; @r{Putting this @code{if} after the @code{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))
-@end group
-@end smallexample
-
-@noindent
-And here is the code to set up the keymap for Lisp mode:
-
-@smallexample
-@group
-(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))
-@end group
-@end smallexample
-
- Finally, here is the complete major mode function definition for
-Lisp mode.
-
-@smallexample
-@group
-(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.
-@end group
-
-@group
-Entry to this mode calls the value of `lisp-mode-hook'
-if that value is non-nil."
- (interactive)
- (kill-all-local-variables)
-@end group
-@group
- (use-local-map lisp-mode-map) ; @r{Select the mode's keymap.}
- (setq major-mode 'lisp-mode) ; @r{This is how @code{describe-mode}}
- ; @r{finds out what to describe.}
- (setq mode-name "Lisp") ; @r{This goes into the mode line.}
- (lisp-mode-variables t) ; @r{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)
-@end group
-@group
- (setq imenu-case-fold-search t)
- (set-syntax-table lisp-mode-syntax-table)
- (run-mode-hooks 'lisp-mode-hook)) ; @r{This permits the user to use a}
- ; @r{hook to customize the mode.}
-@end group
-@end smallexample
-