]> code.delx.au - gnu-emacs/blobdiff - lisp/emacs-lisp/easy-mmode.el
Merge from emacs-24
[gnu-emacs] / lisp / emacs-lisp / easy-mmode.el
index 166c093f37b89282b1c80feb19cb151a21da587d..9a17a75e48b7fbf37be50e4b4cbfdec896fcff37 100644 (file)
@@ -1,6 +1,6 @@
 ;;; easy-mmode.el --- easy definition for major and minor modes
 
-;; Copyright (C) 1997, 2000-2013 Free Software Foundation, Inc.
+;; Copyright (C) 1997, 2000-2014 Free Software Foundation, Inc.
 
 ;; Author: Georges Brun-Cottan <Georges.Brun-Cottan@inria.fr>
 ;; Maintainer: Stefan Monnier <monnier@gnu.org>
@@ -148,7 +148,7 @@ For example, you could write
     :lighter \" Foo\" :require 'foo :global t :group 'hassle :version \"27.5\"
     ...BODY CODE...)"
   (declare (doc-string 2)
-           (debug (&define name stringp
+           (debug (&define name string-or-null-p
                           [&optional [&not keywordp] sexp
                            &optional [&not keywordp] sexp
                            &optional [&not keywordp] sexp]
@@ -296,6 +296,12 @@ the mode if ARG is omitted or nil, and toggle it if ARG is `toggle'.
        ;; up-to-here.
        :autoload-end
 
+       (defvar ,hook nil
+         ,(format "Hook run after entering or leaving `%s'.
+No problems result if this variable is not bound.
+`add-hook' automatically binds it.  (This is true for all hook variables.)"
+                 modefun))
+
        ;; Define the minor-mode keymap.
        ,(unless (symbolp keymap)       ;nil is also a symbol.
          `(defvar ,keymap-sym
@@ -341,9 +347,14 @@ If MODE's set-up depends on the major mode in effect when it was
 enabled, then disabling and reenabling MODE should make MODE work
 correctly with the current major mode.  This is important to
 prevent problems with derived modes, that is, major modes that
-call another major mode in their body."
+call another major mode in their body.
+
+When a major mode is initialized, MODE is actually turned on just
+after running the major mode's hook.  However, MODE is not turned
+on if the hook has explicitly disabled it."
   (declare (doc-string 2))
   (let* ((global-mode-name (symbol-name global-mode))
+        (mode-name (symbol-name mode))
         (pretty-name (easy-mmode-pretty-mode-name mode))
         (pretty-global-name (easy-mmode-pretty-mode-name global-mode))
         (group nil)
@@ -354,6 +365,8 @@ call another major mode in their body."
         (MODE-check-buffers
          (intern (concat global-mode-name "-check-buffers")))
         (MODE-cmhh (intern (concat global-mode-name "-cmhh")))
+        (minor-MODE-hook (intern (concat mode-name "-hook")))
+        (MODE-set-explicitly (intern (concat mode-name "-set-explicitly")))
         (MODE-major-mode (intern (concat (symbol-name mode) "-major-mode")))
         keyw)
 
@@ -397,25 +410,32 @@ See `%s' for more information on %s."
             (progn
               (add-hook 'after-change-major-mode-hook
                         ',MODE-enable-in-buffers)
-              (add-hook 'change-major-mode-after-body-hook
-                        ',MODE-enable-in-buffers)
               (add-hook 'find-file-hook ',MODE-check-buffers)
               (add-hook 'change-major-mode-hook ',MODE-cmhh))
           (remove-hook 'after-change-major-mode-hook ',MODE-enable-in-buffers)
-          (remove-hook 'change-major-mode-after-body-hook
-                       ',MODE-enable-in-buffers)
           (remove-hook 'find-file-hook ',MODE-check-buffers)
           (remove-hook 'change-major-mode-hook ',MODE-cmhh))
 
         ;; Go through existing buffers.
         (dolist (buf (buffer-list))
           (with-current-buffer buf
-            (if ,global-mode (,turn-on) (when ,mode (,mode -1))))))
+            (if ,global-mode (funcall #',turn-on) (when ,mode (,mode -1))))))
 
        ;; Autoloading define-globalized-minor-mode autoloads everything
        ;; up-to-here.
        :autoload-end
 
+       ;; MODE-set-explicitly is set in MODE-set-explicitly and cleared by
+       ;; kill-all-local-variables.
+       (defvar-local ,MODE-set-explicitly nil)
+       (defun ,MODE-set-explicitly ()
+         (setq ,MODE-set-explicitly t))
+       (put ',MODE-set-explicitly 'definition-name ',global-mode)
+
+       ;; A function which checks whether MODE has been disabled in the major
+       ;; mode hook which has just been run.
+       (add-hook ',minor-MODE-hook ',MODE-set-explicitly)
+
        ;; List of buffers left to process.
        (defvar ,MODE-buffers nil)
 
@@ -424,14 +444,14 @@ See `%s' for more information on %s."
         (dolist (buf ,MODE-buffers)
           (when (buffer-live-p buf)
             (with-current-buffer buf
-               (unless (eq ,MODE-major-mode major-mode)
-                 (if ,mode
-                     (progn
-                       (,mode -1)
-                       (,turn-on)
-                       (setq ,MODE-major-mode major-mode))
-                   (,turn-on)
-                   (setq ,MODE-major-mode major-mode)))))))
+               (unless ,MODE-set-explicitly
+                (unless (eq ,MODE-major-mode major-mode)
+                  (if ,mode
+                      (progn
+                        (,mode -1)
+                        (funcall #',turn-on))
+                    (funcall #',turn-on))))
+              (setq ,MODE-major-mode major-mode)))))
        (put ',MODE-enable-in-buffers 'definition-name ',global-mode)
 
        (defun ,MODE-check-buffers ()
@@ -450,18 +470,9 @@ See `%s' for more information on %s."
 ;;; easy-mmode-defmap
 ;;;
 
-(eval-and-compile
-  (if (fboundp 'set-keymap-parents)
-      (defalias 'easy-mmode-set-keymap-parents 'set-keymap-parents)
-    (defun easy-mmode-set-keymap-parents (m parents)
-      (set-keymap-parent
-       m
-       (cond
-        ((not (consp parents)) parents)
-        ((not (cdr parents)) (car parents))
-        (t (let ((m (copy-keymap (pop parents))))
-             (easy-mmode-set-keymap-parents m parents)
-             m)))))))
+(defun easy-mmode-set-keymap-parents (m parents)
+  (set-keymap-parent
+   m (if (cdr parents) (make-composed-keymap parents) (car parents))))
 
 ;;;###autoload
 (defun easy-mmode-define-keymap (bs &optional name m args)
@@ -578,7 +589,7 @@ BODY is executed after moving to the destination location."
                       (prog1 (or (< (- (point-max) (point-min)) (buffer-size)))
                         (widen))))
                  ,body
-                 (when was-narrowed (,narrowfun)))))))
+                 (when was-narrowed (funcall #',narrowfun)))))))
     (unless name (setq name base-name))
     `(progn
        (defun ,next-sym (&optional count)
@@ -590,13 +601,13 @@ BODY is executed after moving to the destination location."
            ,(funcall when-narrowed
              `(if (not (re-search-forward ,re nil t count))
                   (if (looking-at ,re)
-                      (goto-char (or ,(if endfun `(,endfun)) (point-max)))
+                      (goto-char (or ,(if endfun `(funcall #',endfun)) (point-max)))
                     (user-error "No next %s" ,name))
                 (goto-char (match-beginning 0))
-                (when (and (eq (current-buffer) (window-buffer (selected-window)))
+                (when (and (eq (current-buffer) (window-buffer))
                            (called-interactively-p 'interactive))
                   (let ((endpt (or (save-excursion
-                                     ,(if endfun `(,endfun)
+                                     ,(if endfun `(funcall #',endfun)
                                         `(re-search-forward ,re nil t 2)))
                                    (point-max))))
                     (unless (pos-visible-in-window-p endpt nil t)