@c -*-texinfo-*-
@c This is part of the XEmacs Lisp Reference Manual.
-@c Copyright (C) 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
+@c Copyright (C) 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
@c See the file lispref.texi for copying conditions.
@setfilename ../../info/modes.info
@node Modes, Documentation, Drag and Drop, Top
@cindex Fundamental mode
Major modes specialize XEmacs for editing particular kinds of text.
-Each buffer has only one major mode at a time.
+Each buffer has only one major mode at a time. For each major mode
+there is a function to switch to that mode in the current buffer; its
+name should end in @samp{-mode}. These functions work by setting
+buffer-local variable bindings and other data associated with the
+buffer, such as a local keymap. The effect lasts until you switch
+to another major mode in the same buffer.
The least specialized major mode is called @dfn{Fundamental mode}.
This mode has no mode-specific definitions or variable settings, so each
Text mode except that it provides three additional commands. Its
definition is distinct from that of Text mode, but was derived from it.
+ Even if the new mode is not an obvious derivative of any other mode,
+it is convenient to use @code{define-derived-mode} with a @code{nil}
+parent argument, since it automatically enforces the most important
+coding conventions for you.
+
Rmail Edit mode is an example of a case where one piece of text is put
temporarily into a different major mode so it can be edited in a
different way (with ordinary XEmacs commands rather than Rmail). In such
* Example Major Modes:: Text mode and Lisp modes.
* Auto Major Mode:: How XEmacs chooses the major mode automatically.
* Mode Help:: Finding out how to use a mode.
-* Derived Modes:: Defining a new major mode based on another major
+* Derived Modes:: Defining a new major mode based on another major
mode.
@end menu
or it may run them earlier.
@item
+The major mode command may start by calling some other major mode
+command (called the @dfn{parent mode}) and then alter some of its
+settings. A mode that does this is called a @dfn{derived mode}. The
+recommended way to define one is to use @code{define-derived-mode},
+but this is not required. Such a mode should use
+@code{delay-mode-hooks} around its entire body, including the call to
+the parent mode command and the final call to @code{run-mode-hooks}.
+(Using @code{define-derived-mode} does this automatically.)
+
+@item
If something special should be done if the user switches a buffer from
this mode to any other major mode, the mode can set a local value for
@code{change-major-mode-hook}.
@smallexample
@group
;; @r{Create mode-specific tables.}
-(defvar text-mode-syntax-table nil
+(defvar text-mode-syntax-table nil
"Syntax table used while in text mode.")
@end group
@smallexample
@group
(defun text-mode ()
- "Major mode for editing text intended for humans to read.
+ "Major mode for editing text intended for humans to read.
Special commands: \\@{text-mode-map@}
@end group
@group
@smallexample
@group
;; @r{Create mode-specific table variables.}
-(defvar lisp-mode-syntax-table nil "")
+(defvar lisp-mode-syntax-table nil "")
(defvar emacs-lisp-mode-syntax-table nil "")
(defvar lisp-mode-abbrev-table nil "")
@end group
;; @r{Set syntax of chars up to 0 to class of chars that are}
;; @r{part of symbol names but not words.}
;; @r{(The number 0 is @code{48} in the @sc{ascii} character set.)}
- (while (< i ?0)
+ (while (< i ?0)
(modify-syntax-entry i "_ " emacs-lisp-mode-syntax-table)
(setq i (1+ i)))
@dots{}
@smallexample
@group
-(defvar emacs-lisp-mode-map () "")
+(defvar emacs-lisp-mode-map () "")
(if emacs-lisp-mode-map
()
(setq emacs-lisp-mode-map (make-sparse-keymap))
@end smallexample
Finally, here is the complete major mode function definition for
-Emacs Lisp mode.
+Emacs Lisp mode.
@smallexample
@group
If you run @code{normal-mode} interactively, the argument
@var{find-file} is normally @code{nil}. In this case,
@code{normal-mode} unconditionally processes any local variables list.
-@xref{File variables, , Local Variables in Files, emacs, The XEmacs
+@xref{File variables, , Local Variables in Files, xemacs, The XEmacs
Reference Manual}, for the syntax of the local variables section of a file.
@cindex file mode specification error
value of a local variable. However, this function does not look for
the @samp{mode:} local variable near the end of a file; the
@code{hack-local-variables} function does that. @xref{Choosing Modes, ,
-How Major Modes are Chosen, emacs, The XEmacs Reference Manual}.
+How Major Modes are Chosen, xemacs, The XEmacs Lisp Reference Manual}.
@end defun
-@defopt default-major-mode
+@defopt default-major-mode
This variable holds the default major mode for new buffers. The
standard value is @code{fundamental-mode}.
@end group
@group
("\\.el\\'" . emacs-lisp-mode)
- ("\\.c\\'" . c-mode)
+ ("\\.c\\'" . c-mode)
("\\.h\\'" . c-mode)
@dots{})
@end group
@smallexample
@group
(setq auto-mode-alist
- (append
+ (append
;; @r{File name starts with a dot.}
- '(("/\\.[^/]*\\'" . fundamental-mode)
+ '(("/\\.[^/]*\\'" . fundamental-mode)
;; @r{File name has no dot.}
- ("[^\\./]*\\'" . fundamental-mode)
+ ("[^\\./]*\\'" . fundamental-mode)
;; @r{File name ends in @samp{.C}.}
("\\.C\\'" . c++-mode))
auto-mode-alist))
The new command @var{variant} is defined to call the function
@var{parent}, then override certain aspects of that parent mode:
-@itemize @bullet
+@itemize @bullet
@item
The new mode has its own keymap, named @code{@var{variant}-map}.
@code{define-derived-mode} initializes this map to inherit from
@item
The new mode has its own syntax table, kept in the variable
@code{@var{variant}-syntax-table}.
-@code{define-derived-mode} initializes this variable by copying
+@code{define-derived-mode} initializes this variable by copying
@code{@var{parent}-syntax-table}, if it is not already set.
@item
The new mode has its own abbrev table, kept in the variable
@code{@var{variant}-abbrev-table}.
-@code{define-derived-mode} initializes this variable by copying
+@code{define-derived-mode} initializes this variable by copying
@code{@var{parent}-abbrev-table}, if it is not already set.
@item
The new mode has its own mode hook, @code{@var{variant}-hook},
which it runs in standard fashion as the very last thing that it does.
-(The new mode also runs the mode hook of @var{parent} as part
+(The new mode also runs the mode hook of @var{parent} as part
of calling @var{parent}.)
@end itemize
In addition, you can specify how to override other aspects of
@var{parent} with @var{body}. The command @var{variant}
-evaluates the forms in @var{body} after setting up all its usual
+evaluates the forms in @var{body} after setting up all its usual
overrides, just before running @code{@var{variant}-hook}.
The argument @var{docstring} specifies the documentation string for the
(define-key hypertext-mode-map
[down-mouse-3] 'do-hyper-link)
@end example
+
+Do not write an @code{interactive} spec in the definition;
+@code{define-derived-mode} does that automatically.
@end defmac
@node Minor Modes
(setq modeline-format
(list ""
'modeline-modified
- "%b--"
+ "%b--"
@end group
(getenv "HOST") ; @r{One element is not constant.}
- ":"
+ ":"
'default-directory
" "
'global-mode-string
" %[("
- 'mode-name
- 'modeline-process
- 'minor-mode-alist
- "%n"
+ 'mode-name
+ 'modeline-process
+ 'minor-mode-alist
+ "%n"
")%]----"
@group
'(line-number-mode "L%l--")
@group
minor-mode-alist
@result{} ((vc-mode vc-mode)
- (abbrev-mode " Abbrev")
- (overwrite-mode overwrite-mode)
- (auto-fill-function " Fill")
+ (abbrev-mode " Abbrev")
+ (overwrite-mode overwrite-mode)
+ (auto-fill-function " Fill")
(defining-kbd-macro " Def")
(isearch-mode isearch-mode))
@end group
" "
global-mode-string
" %[("
- mode-name
+ mode-name
@end group
@group
modeline-process
- minor-mode-alist
- "%n"
+ minor-mode-alist
+ "%n"
")%]----"
(line-number-mode "L%l--")
(-3 . "%p")
Most of the hooks in XEmacs are @dfn{normal hooks}. These variables
contain lists of functions to be called with no arguments. The reason
most hooks are normal hooks is so that you can use them in a uniform
-way. You can usually tell when a hook is a normal hook, because its
+way. You can usually tell when a hook is a normal hook, because its
name ends in @samp{-hook}.
The recommended way to add a hook function to a normal hook is by
@cindex lambda expression in hook
@example
@group
-(add-hook 'c-mode-hook
+(add-hook 'c-mode-hook
(function (lambda ()
(setq c-indent-level 4
c-argdecl-indent 0
(setq modeline-format
'(modeline-modified
"Emacs: %14b"
- " "
+ " "
@end group
@group
default-directory
" "
global-mode-string
- "%[("
- mode-name
- minor-mode-alist
- "%n"
- modeline-process
+ "%[("
+ mode-name
+ minor-mode-alist
+ "%n"
+ modeline-process
") %]---"
(-3 . "%p")
"-%-")))))
@end example
@end defun
+@defun run-mode-hooks &rest hookvars
+Like @code{run-hooks}, but is affected by the @code{delay-mode-hooks}
+macro.
+@end defun
+
+@defmac delay-mode-hooks body...
+This macro executes the @var{body} forms but defers all calls to
+@code{run-mode-hooks} within them until the end of @var{body}.
+This macro enables a derived mode to arrange not to run
+its parent modes' mode hooks until the end.
+@end defmac
+
+@defun run-hook-with-args hook &rest args
+This function is the way to run an abnormal hook and always call all
+of the hook functions. It calls each of the hook functions one by
+one, passing each of them the arguments @var{args}.
+@end defun
+
+@defun run-hook-with-args-until-failure hook &rest args
+This function is the way to run an abnormal hook until one of the hook
+functions fails. It calls each of the hook functions, passing each of
+them the arguments @var{args}, until some hook function returns
+@code{nil}. It then stops and returns @code{nil}. If none of the
+hook functions return @code{nil}, it returns a non-@code{nil} value.
+@end defun
+
+@defun run-hook-with-args-until-success hook &rest args
+This function is the way to run an abnormal hook until a hook function
+succeeds. It calls each of the hook functions, passing each of them
+the arguments @var{args}, until some hook function returns
+non-@code{nil}. Then it stops, and returns whatever was returned by
+the last hook function that was called. If all hook functions return
+@code{nil}, it returns @code{nil} as well.
+@end defun
+
@defun add-hook hook function &optional append local
This function is the handy way to add function @var{function} to hook
variable @var{hook}. The argument @var{function} may be any valid Lisp
@end defun
@defun make-local-hook hook
-This function makes the hook variable @code{hook} local to the current
+This function makes the hook variable @var{hook} local to the current
buffer. When a hook variable is local, it can have local and global
hook functions, and @code{run-hooks} runs all of them.