Update copyright and commentary.

(easy-mmode-define-toggle): Deprecate the use of *-(on|off)-hook.
Print a status message if the toggle is called interactively.
(define-minor-mode): Allow INIT-VALUE to be (global . INIT-VALUE)
for global minor modes and use `defcustom' for them.
Use add-minor-mode.
(easy-mmode-define-derived-mode): Remove.
(define-derived-mode): Fancier default docstring.
(easy-mmode-define-navigation): Signal an error rather than (ding).
This commit is contained in:
Stefan Monnier 2000-05-21 01:44:08 +00:00
parent 9b0d1d6e8d
commit c8c21615b8
2 changed files with 67 additions and 58 deletions

View file

@ -1,6 +1,6 @@
;;; easy-mmode.el --- easy definition for major and minor modes.
;; Copyright (C) 1997 Free Software Foundation, Inc.
;; Copyright (C) 1997,2000 Free Software Foundation, Inc.
;; Author: Georges Brun-Cottan <Georges.Brun-Cottan@inria.fr>
;; Maintainer: Stefan Monnier <monnier@gnu.org>
@ -33,11 +33,11 @@
;; For each mode, easy-mmode defines the following:
;; <mode> : The minor mode predicate. A buffer-local variable.
;; <mode>-map : The keymap possibly associated to <mode>.
;; <mode>-hook,<mode>-on-hook,<mode>-off-hook and <mode>-mode:
;; see `easy-mmode-define-minor-mode' documentation
;; <mode>-hook : The hook run at the end of the toggle function.
;; see `define-minor-mode' documentation
;;
;; eval
;; (pp (macroexpand '(easy-mmode-define-minor-mode <your-mode> <doc>)))
;; (pp (macroexpand '(define-minor-mode <your-mode> <doc>)))
;; to check the result before using it.
;; The order in which minor modes are installed is important. Keymap
@ -55,16 +55,7 @@
"Define a one arg toggle mode MODE function and associated hooks.
MODE is the so defined function that toggles the mode.
optional DOC is its associated documentation.
BODY is executed after the toggling and before running the hooks.
Hooks are checked for run, each time MODE-mode is called.
They run under the followings conditions:
MODE-hook: if the mode is toggled.
MODE-on-hook: if the mode is on.
MODE-off-hook: if the mode is off.
When the mode is effectively toggled, two hooks may run.
If so MODE-hook is guaranteed to be the first."
BODY is executed after the toggling and before running MODE-hook."
(let* ((mode-name (symbol-name mode))
(hook (intern (concat mode-name "-hook")))
(hook-on (intern (concat mode-name "-on-hook")))
@ -76,28 +67,27 @@ With zero or negative ARG turn mode off.
\\{%s}" mode-name (concat mode-name "-map")))))
`(progn
(defcustom ,hook nil
,(format "Hook called when `%s' is toggled" mode-name)
:type 'hook)
(defcustom ,hook-on nil
,(format "Hook called when `%s' is turned on" mode-name)
:type 'hook)
(defcustom ,hook-off nil
,(format "Hook called when `%s' is turned off" mode-name)
,(format "Hook called at the end of function `%s'." mode-name)
:type 'hook)
(defun ,mode (&optional arg)
,toggle-doc
(interactive "P")
(let ((old-mode ,mode))
(setq ,mode
(if arg
(> (prefix-numeric-value arg) 0)
(not ,mode)))
,@body
(unless (equal old-mode ,mode) (run-hooks ',hook))
(run-hooks (if ,mode ',hook-on ',hook-off)))))))
(setq ,mode
(if arg
(> (prefix-numeric-value arg) 0)
(not ,mode)))
,@body
;; The on/off hooks are here for backward compatibility.
(run-hooks ',hook (if ,mode ',hook-on ',hook-off))
;; Return the new setting.
(if (interactive-p)
(message ,(format "%s %%sabled"
(replace-regexp-in-string
"-Mode" " mode"
(capitalize (symbol-name mode)) t))
(if ,mode "en" "dis")))
,mode))))
;;;###autoload
(defalias 'easy-mmode-define-minor-mode 'define-minor-mode)
@ -109,21 +99,35 @@ toggle command, and hooks (see `easy-mmode-define-toggle').
DOC is the documentation for the mode toggle command.
Optional INIT-VALUE is the initial value of the mode's variable.
Optional LIGHTER is displayed in the mode-bar when the mode is on.
By default, the variable is made buffer-local. This can be overridden
by specifying an initial value of (global . INIT-VALUE).
Optional LIGHTER is displayed in the modeline when the mode is on.
Optional KEYMAP is the default (defvar) keymap bound to the mode keymap.
If it is a list, it is passed to `easy-mmode-define-keymap'
in order to build a valid keymap.
BODY contains code that will be executed each time the mode is (dis)activated.
It will be executed after any toggling but before running the hooks."
(let* ((mode-name (symbol-name mode))
(mode-doc (format "Non-nil if mode is enabled.
Use the function `%s' to change this variable." mode-name))
(globalp nil)
(keymap-sym (intern (concat mode-name "-map")))
(keymap-doc (format "Keymap for `%s'." mode-name)))
;; Check if the mode should be global.
(when (and (consp init-value) (eq (car init-value) 'global))
(setq init-value (cdr init-value) globalp t))
`(progn
;; Define the variable to enable or disable the mode.
(defvar ,mode ,init-value ,mode-doc)
(make-variable-buffer-local ',mode)
,(if globalp
`(defcustom ,mode ,init-value ,(format "Toggle %s.
Setting this variable directly does not take effect;
use either \\[customize] or the function `%s'." mode mode)
:set (lambda (symbol value) (funcall symbol (or value 0)))
:initialize 'custom-initialize-default
:type 'boolean)
`(progn
(defvar ,mode ,init-value ,(format "Non-nil if mode is enabled.
Use the function `%s' to change this variable." mode))
(make-variable-buffer-local ',mode)))
;; Define the minor-mode keymap.
,(when keymap
@ -137,20 +141,11 @@ Use the function `%s' to change this variable." mode-name))
;; Define the toggle and the hooks.
(easy-mmode-define-toggle ,mode ,doc ,@body)
;; Update the mode line.
(or (assq ',mode minor-mode-alist)
(setq minor-mode-alist
(cons (list ',mode nil) minor-mode-alist)))
(setcar (cdr (assq ',mode minor-mode-alist)) ,lighter)
;; Update the minor mode map.
(or (assq ',mode minor-mode-map-alist)
(setq minor-mode-map-alist
(cons (cons ',mode nil) minor-mode-map-alist)))
(setcdr (assq ',mode minor-mode-map-alist)
,keymap-sym)) ))
(add-minor-mode ',mode ,lighter
(if (boundp ',keymap-sym) (symbol-value ',keymap-sym)))
;; If the mode is global, call the function according to the default.
,(if globalp `(if ,mode (,mode 1))))))
;;;
;;; easy-mmode-defmap
@ -240,7 +235,6 @@ ARGS is a list of additional arguments."
;;; A "macro-only" reimplementation of define-derived-mode.
;;;
(defalias 'easy-mmode-define-derived-mode 'define-derived-mode)
;;;###autoload
(defmacro define-derived-mode (child parent name &optional docstring &rest body)
"Create a new mode as a variant of an existing mode.
@ -298,10 +292,16 @@ which more-or-less shadow %s's corresponding tables."
(unless (string-match (regexp-quote (symbol-name hook)) docstring)
;; Make sure the docstring mentions the mode's hook
(setq docstring (format "%s
This mode runs (additionally to any hooks his parent might have run)
its own `%s' just before exiting."
docstring hook)))
(setq docstring
(concat docstring
(unless (eq parent 'fundamental-mode)
(concat
"\nAdditionally to any hooks its parent mode "
(if (string-match (regexp-quote (format "`%s'" parent))
docstring) nil
(format "`%s' " parent))
"might have run),"))
(format "\nThis mode runs `%s' just before exiting." hook))))
(unless (string-match "\\\\[{[]" docstring)
;; And don't forget to put the mode's keymap
@ -372,7 +372,7 @@ ENDFUN should return the end position (with or without moving point)."
(if (< count 0) (,prev-sym (- count))
(if (looking-at ,re) (incf count))
(unless (re-search-forward ,re nil t count)
(if (interactive-p) (ding) (error ,(format "No next %s" name))))
(error ,(format "No next %s" name)))
(goto-char (match-beginning 0))
(when (eq (current-buffer) (window-buffer (selected-window)))
(let ((endpt (or (save-excursion
@ -386,8 +386,7 @@ ENDFUN should return the end position (with or without moving point)."
(unless count (setq count 1))
(if (< count 0) (,next-sym (- count))
(unless (re-search-backward ,re nil t count)
(if (interactive-p) (ding)
(error ,(format "No previous %s" name)))))))))
(error ,(format "No previous %s" name))))))))
(provide 'easy-mmode)