-;;; easy-mmode.el --- easy definition for major and minor modes.
+;;; easy-mmode.el --- easy definition for major and minor modes
-;; Copyright (C) 1997,2000 Free Software Foundation, Inc.
+;; Copyright (C) 1997, 2000, 2001 Free Software Foundation, Inc.
-;; Author: Georges Brun-Cottan <Georges.Brun-Cottan@inria.fr>
-;; Maintainer: Stefan Monnier <monnier@gnu.org>
+;; Author: Georges Brun-Cottan <Georges.Brun-Cottan@inria.fr>
+;; Maintainer: Stefan Monnier <monnier@gnu.org>
+
+;; Keywords: extensions lisp
;; This file is part of GNU Emacs.
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.
- BODY can start with a list of CL-style keys specifying additional arguments.
- The following keyword arguments are supported:
-:group Followed by the group name to use for any generated `defcustom'.
-:global If non-nil specifies that the minor mode is not meant to be
- buffer-local. By default, the variable is made buffer-local.
-:init-value Same as the INIT-VALUE argument.
-:lighter Same as the LIGHTER argument."
+ Before the actual body code, you can write
+ keyword arguments (alternating keywords and values).
+ These following keyword arguments are supported:
+:group GROUP Custom group name to use in all generated `defcustom' forms.
+:global GLOBAL If non-nil specifies that the minor mode is not meant to be
+ buffer-local, so don't make the variable MODE buffer-local.
+ By default, the mode is buffer-local.
+:init-value VAL Same as the INIT-VALUE argument.
+:lighter SPEC Same as the LIGHTER argument.
+:require SYM Same as in `defcustom'.
+
+For example, you could write
+ (define-minor-mode foo-mode \"If enabled, foo on you!\"
+ nil \"Foo \" foo-keymap
+ :require 'foo :global t :group 'inconvenience
+ ...BODY CODE...)"
+
;; Allow skipping the first three args.
(cond
((keywordp init-value)
(let* ((mode-name (symbol-name mode))
(pretty-name (easy-mmode-pretty-mode-name mode lighter))
(globalp nil)
- (togglep t) ;why would you ever want to toggle?
(group nil)
(extra-args nil)
+ (require t)
(keymap-sym (if (and keymap (symbolp keymap)) keymap
(intern (concat mode-name "-map"))))
(hook (intern (concat mode-name "-hook")))
(:global (setq globalp (pop body)))
(:extra-args (setq extra-args (pop body)))
(:group (setq group (nconc group (list :group (pop body)))))
+ (:require (setq require (pop body)))
(t (pop body))))
(unless group
;; We might as well provide a best-guess default group.
(setq group
- `(:group ',(intern (replace-regexp-in-string "-mode\\'" ""
- mode-name)))))
- ;; Add default properties to LIGHTER.
- (unless (or (not (stringp lighter)) (get-text-property 0 'local-map lighter)
- (get-text-property 0 'keymap lighter))
- (setq lighter
- (apply 'propertize lighter
- 'local-map (make-mode-line-mouse2-map mode)
- (unless (get-text-property 0 'help-echo lighter)
- (list 'help-echo
- (format "mouse-2: turn off %s" pretty-name))))))
+ `(:group ',(or (custom-current-group)
+ (intern (replace-regexp-in-string
+ "-mode\\'" "" mode-name))))))
`(progn
;; Define the variable to enable or disable the mode.
:initialize 'custom-initialize-default
,@group
:type 'boolean
- ,@(when curfile
- (list
- :require
- (list 'quote
- (intern (file-name-nondirectory
- (file-name-sans-extension curfile)))))))))
+ ,@(cond
+ ((not (and curfile require)) nil)
+ ((not (eq require t)) `(:require ,require))
+ (t `(:require
+ ',(intern (file-name-nondirectory
+ (file-name-sans-extension curfile)))))))))
;; The actual function.
(defun ,mode (&optional arg ,@extra-args)
,(or doc
(format (concat "Toggle %s on or off.
Interactively, with no prefix argument, toggle the mode.
-With universal prefix ARG " (unless togglep "(or if ARG is nil) ") "turn mode on.
+With universal prefix ARG turn mode on.
With zero or negative ARG turn mode off.
\\{%s}") pretty-name keymap-sym))
- (interactive (list (or current-prefix-arg (if ,mode 0 1))))
+ ;; Use `toggle' rather than (if ,mode 0 1) so that using
+ ;; repeat-command still does the toggling correctly.
+ (interactive (list (or current-prefix-arg 'toggle)))
(setq ,mode
- (if arg
- (> (prefix-numeric-value arg) 0)
- ,(if togglep `(not ,mode) t)))
+ (cond
+ ((eq arg 'toggle) (not ,mode))
+ (arg (> (prefix-numeric-value arg) 0))
+ (t
+ (if (null ,mode) t
+ (message
+ "Toggling %s off; better pass an explicit argument."
+ ',mode)
+ nil))))
,@body
;; The on/off hooks are here for backward compatibility only.
(run-hooks ',hook (if ,mode ',hook-on ',hook-off))
- ;; Return the new setting.
(if (interactive-p)
- (message ,(format "%s %%sabled" pretty-name)
- (if ,mode "en" "dis")))
+ (progn
+ ,(if globalp `(customize-mark-as-set ',mode))
+ (message ,(format "%s %%sabled" pretty-name)
+ (if ,mode "en" "dis"))))
(force-mode-line-update)
+ ;; Return the new setting.
,mode)
;; Autoloading an easy-mmode-define-minor-mode autoloads
;; The toggle's hook.
(defcustom ,hook nil
,(format "Hook run at the end of function `%s'." mode-name)
- :group ,(cadr group)
+ ,@group
:type 'hook)
;; Define the minor-mode keymap.
(symbol-value ',keymap-sym))))
;; If the mode is global, call the function according to the default.
- ,(if globalp `(if ,mode (,mode 1))))))
+ ,(if globalp
+ `(if (and load-file-name (not (equal ,init-value ,mode)))
+ (eval-after-load load-file-name '(,mode (if ,mode 1 -1))))))))
\f
;;;
;;; make global minor mode
(unless group
;; We might as well provide a best-guess default group.
(setq group
- `(:group ',(intern (replace-regexp-in-string "-mode\\'" ""
- (symbol-name mode))))))
+ `(:group ',(or (custom-current-group)
+ (intern (replace-regexp-in-string
+ "-mode\\'" "" (symbol-name mode)))))))
+
`(progn
;; The actual global minor-mode
(define-minor-mode ,global-mode
;; Setup hook to handle future mode changes and new buffers.
(if ,global-mode
(progn
- (add-hook 'find-file-hooks ',buffers)
+ (add-hook 'find-file-hook ',buffers)
(add-hook 'change-major-mode-hook ',cmmh))
- (remove-hook 'find-file-hooks ',buffers)
+ (remove-hook 'find-file-hook ',buffers)
(remove-hook 'change-major-mode-hook ',cmmh))
;; Go through existing buffers.
(let ((buf (pop ,buffers)))
(when (buffer-live-p buf)
(with-current-buffer buf (,turn-on))))))
+ (put ',buffers 'definition-name ',global-mode)
;; The function that catches kill-all-local-variables.
(defun ,cmmh ()
(add-to-list ',buffers (current-buffer))
- (add-hook 'post-command-hook ',buffers)))))
+ (add-hook 'post-command-hook ',buffers))
+ (put ',cmmh 'definition-name ',global-mode))))
;;;
;;; easy-mmode-defmap
;;;###autoload
(defmacro easy-mmode-defsyntax (st css doc &rest args)
"Define variable ST as a syntax-table.
-CSS contains a list of syntax specifications of the form (CHAR . SYNTAX).
-"
+CSS contains a list of syntax specifications of the form (CHAR . SYNTAX)."
`(progn
(autoload 'easy-mmode-define-syntax "easy-mmode")
- (defconst ,st (easy-mmode-define-syntax ,css ,(cons 'list args)) doc)))
+ (defconst ,st (easy-mmode-define-syntax ,css ,(cons 'list args)) ,doc)))
\f
(goto-char (or ,(if endfun `(,endfun)) (point-max)))
(error ,(format "No next %s" name)))
(goto-char (match-beginning 0))
- (when (eq (current-buffer) (window-buffer (selected-window)))
+ (when (and (eq (current-buffer) (window-buffer (selected-window)))
+ (interactive-p))
(let ((endpt (or (save-excursion
,(if endfun `(,endfun)
`(re-search-forward ,re nil t 2)))