;;; mode-local.el --- Support for mode local facilities
;;
-;; Copyright (C) 2004, 2005, 2007, 2008, 2009 Free Software Foundation, Inc.
+;; Copyright (C) 2004, 2005, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
;;
;; Author: David Ponce <david@dponce.com>
;; Maintainer: David Ponce <david@dponce.com>
;; that nature, and also provides reasonable defaults.
;;
;; There are buffer local variables, and frame local variables.
-;; This library give the illusion of mode specific variables.
+;; This library gives the illusion of mode specific variables.
;;
;; You should use a mode-local variable or override to allow extension
;; only if you expect a mode author to provide that extension. If a
;; To Do:
;; Allow customization of a variable for a specific mode?
;;
-;; Add mecro for defining the '-default' functionality.
-
-;;; History:
-;;
+;; Add macro for defining the '-default' functionality.
;;; Code:
-(eval-when-compile (require 'cl))
-;;; Compatibility
-;;
-(defun mode-local-define-derived-mode-needed-p ()
- "Return non-nil if mode local has to fix `define-derived-mode'.
-That is, if `define-derived-mode' does not set `derived-mode-parent'."
- (let ((body (cdr (macroexpand '(define-derived-mode c p ""))))
- (bad t))
- (while (and body bad)
- (if (equal (car body) '(put 'c 'derived-mode-parent 'p))
- (setq bad nil)
- (setq body (cdr body))))
- bad))
-
-(when (mode-local-define-derived-mode-needed-p)
- ;; Workaround a bug in some (XEmacs) versions of
- ;; `define-derived-mode' that don't set the `derived-mode-parent'
- ;; property, and break mode-local.
- (defadvice define-derived-mode
- (after mode-local-define-derived-mode activate)
- "Fix missing `derived-mode-parent' property on child."
- (unless (eq 'fundamental-mode (ad-get-arg 1))
- (let ((form (cdr ad-return-value)))
- (setq ad-return-value nil)
- (while form
- (and (eq 'defun (car-safe (car form)))
- (eq (ad-get-arg 0) (car (cdr-safe (car form))))
- (push `(or (get ',(ad-get-arg 0) 'derived-mode-parent)
- (put ',(ad-get-arg 0) 'derived-mode-parent
- ',(ad-get-arg 1)))
- ad-return-value))
- (push (car form) ad-return-value)
- (setq form (cdr form)))
- (setq ad-return-value `(progn ,@(nreverse ad-return-value)))
- )))
- )
+(eval-when-compile (require 'cl))
;;; Misc utilities
;;
(or (get mode 'mode-local-parent)
(get mode 'derived-mode-parent)))
+;; FIXME doc (and function name) seems wrong.
+;; Return a list of MODE and all its parent modes, if any.
+;; Lists parent modes first.
(defun mode-local-equivalent-mode-p (mode)
"Is the major-mode in the current buffer equivalent to a mode in MODES."
(let ((modes nil))
(eq mode-local--init-mode major-mode))
(defun mode-local-post-major-mode-change ()
- "`post-command-hook' run when there is a `major-mode' change.
-This makes sure mode local init type stuff can occur."
+ "Initialize mode-local facilities.
+This is run from `find-file-hook', and from `post-command-hook'
+after changing the major mode."
(remove-hook 'post-command-hook 'mode-local-post-major-mode-change nil)
(let ((buffers mode-local-changed-mode-buffers))
(setq mode-local-changed-mode-buffers nil)
(mode-local-map-file-buffers
- #'(lambda ()
- ;; Make sure variables are set up for this mode.
- (activate-mode-local-bindings)
- (run-hooks 'mode-local-init-hook))
- #'(lambda ()
- (not (mode-local-initialized-p)))
+ (lambda ()
+ ;; Make sure variables are set up for this mode.
+ (activate-mode-local-bindings)
+ (run-hooks 'mode-local-init-hook))
+ (lambda ()
+ (not (mode-local-initialized-p)))
buffers)))
(defun mode-local-on-major-mode-change ()
"Function called in `change-major-mode-hook'."
(add-to-list 'mode-local-changed-mode-buffers (current-buffer))
(add-hook 'post-command-hook 'mode-local-post-major-mode-change t nil))
-
-(add-hook 'find-file-hooks 'mode-local-post-major-mode-change)
-(add-hook 'change-major-mode-hook 'mode-local-on-major-mode-change)
\f
;;; Mode lineage
;;
The current mode bindings are saved, BODY is evaluated, and the saved
bindings are restored, even in case of an abnormal exit.
Value is what BODY returns.
-This lis like `with-mode-local-symbol', except that MODE is quoted
-and is note evaluated."
+This is like `with-mode-local-symbol', except that MODE is quoted
+and is not evaluated."
`(with-mode-local-symbol ',mode ,@body))
(put 'with-mode-local 'lisp-indent-function 1)
\f
;;; Function overloading
;;
-(defun make-obsolete-overload (old new)
- "Mark OLD overload as obsoleted by NEW overload."
+(defun make-obsolete-overload (old new when)
+ "Mark OLD overload as obsoleted by NEW overload.
+WHEN is a string describing the first release where it was made obsolete."
(put old 'overload-obsoleted-by new)
+ (put old 'overload-obsoleted-since when)
(put old 'mode-local-overload t)
(put new 'overload-obsolete old))
(defun overload-docstring-extension (overload)
"Return the doc string that augments the description of OVERLOAD."
(let ((doc "\n\This function can be overloaded\
- (see `define-mode-local-override' for details).")
+ with `define-mode-local-override'.")
(sym (overload-obsoleted-by overload)))
(when sym
- (setq doc (format "%s\nIt makes the overload `%s' obsolete."
- doc sym)))
+ (setq doc (format "%s\nIt has made the overload `%s' obsolete since %s."
+ doc sym (get sym 'overload-obsoleted-since))))
(setq sym (overload-that-obsolete overload))
(when sym
- (setq doc (format "%s\nThis overload is obsoletes;\nUse `%s' instead."
- doc sym)))
+ (setq doc (format "%s\nThis overload is obsolete since %s;\nUse `%s' instead."
+ doc (get overload 'overload-obsoleted-since) sym)))
doc))
(defun mode-local-augment-function-help (symbol)
)
(toggle-read-only 1))))
-;; Help for Overload functions. Need to advise help.
-(defadvice describe-function (around mode-local-help activate)
- "Display the full documentation of FUNCTION (a symbol).
-Returns the documentation as a string, also."
- (prog1
- ad-do-it
- (if (function-overload-p (ad-get-arg 0))
- (mode-local-augment-function-help (ad-get-arg 0)))))
-
;; Help for mode-local bindings.
(defun mode-local-print-binding (symbol)
"Print the SYMBOL binding."
"Display mode local bindings active in BUFFER."
(interactive "b")
(when (setq buffer (get-buffer buffer))
- (mode-local-describe-bindings-1 buffer (interactive-p))))
+ (mode-local-describe-bindings-1 buffer (called-interactively-p 'any))))
(defun describe-mode-local-bindings-in-mode (mode)
"Display mode local bindings active in MODE hierarchy."
#'(lambda (s) (get s 'mode-local-symbol-table))
t (symbol-name major-mode))))
(when (setq mode (intern-soft mode))
- (mode-local-describe-bindings-1 mode (interactive-p))))
+ (mode-local-describe-bindings-1 mode (called-interactively-p 'any))))
\f
-;;; Font-lock support
-;;
-(defconst mode-local-font-lock-keywords
- (eval-when-compile
- (let* (
- ;; Variable declarations
- (kv (regexp-opt
- '(
- "defconst-mode-local"
- "defvar-mode-local"
- ) t))
- ;; Function declarations
- (kf (regexp-opt
- '(
- "define-mode-local-override"
- "define-child-mode"
- "define-overload"
- "define-overloadable-function"
- ;;"make-obsolete-overload"
- "with-mode-local"
- ) t))
- ;; Regexp depths
- (kv-depth (regexp-opt-depth kv))
- (kf-depth (regexp-opt-depth kf))
- )
- `((,(concat
- ;; Declarative things
- "(\\(" kv "\\|" kf "\\)"
- ;; Whitespaces & names
- "\\>[ \t]*\\(\\sw+\\)?[ \t]*\\(\\sw+\\)?"
- )
- (1 font-lock-keyword-face)
- (,(+ 1 kv-depth kf-depth 1)
- (cond ((match-beginning 2)
- font-lock-type-face)
- ((match-beginning ,(+ 1 kv-depth 1))
- font-lock-function-name-face)
- )
- nil t)
- (,(+ 1 kv-depth kf-depth 1 1)
- (cond ((match-beginning 2)
- font-lock-variable-name-face)
- )
- nil t)))
- ))
- "Highlighted keywords.")
-
-\f
-;;; find-func support (Emacs 21.4, or perhaps 22.1)
-;;
-(condition-case nil
- ;; Try to get find-func so we can modify it.
- (require 'find-func)
- (error nil))
-
-(when (boundp 'find-function-regexp)
- (unless (string-match "ine-overload" find-function-regexp)
- (if (string-match "(def\\\\(" find-function-regexp)
- (let ((end (match-end 0))
- )
- (setq find-function-regexp
- (concat (substring find-function-regexp 0 end)
- "ine-overload\\|ine-mode-local-override\\|"
- "ine-child-mode\\|"
- (substring find-function-regexp end)))))
- )
- ;; The regexp for variables is a little more kind.
- )
-
-;; TODO: Add XEmacs support
-;; (when (fboundp 'font-lock-add-keywords)
-;; (font-lock-add-keywords 'emacs-lisp-mode
-;; mode-local-font-lock-keywords))
+;; ;;; find-func support (Emacs 21.4, or perhaps 22.1)
+;; ;;
+;; (condition-case nil
+;; ;; Try to get find-func so we can modify it.
+;; (require 'find-func)
+;; (error nil))
+
+;; (when (boundp 'find-function-regexp)
+;; (unless (string-match "ine-overload" find-function-regexp)
+;; (if (string-match "(def\\\\(" find-function-regexp)
+;; (let ((end (match-end 0))
+;; )
+;; (setq find-function-regexp
+;; (concat (substring find-function-regexp 0 end)
+;; "ine-overload\\|ine-mode-local-override\\|"
+;; "ine-child-mode\\|"
+;; (substring find-function-regexp end)))))))
\f
;;; edebug support
;;
(defun mode-local-setup-edebug-specs ()
"Define edebug specification for mode local macros."
(def-edebug-spec setq-mode-local
- (symbolp &rest symbolp form)
- )
+ (symbolp &rest symbolp form))
(def-edebug-spec defvar-mode-local
- (&define symbolp name def-form [ &optional stringp ] )
- )
+ (&define symbolp name def-form [ &optional stringp ] ))
(def-edebug-spec defconst-mode-local
- defvar-mode-local
- )
+ defvar-mode-local)
(def-edebug-spec define-overload
- (&define name lambda-list stringp def-body)
- )
+ (&define name lambda-list stringp def-body))
(def-edebug-spec define-overloadable-function
- (&define name lambda-list stringp def-body)
- )
+ (&define name lambda-list stringp def-body))
(def-edebug-spec define-mode-local-override
- (&define name symbolp lambda-list stringp def-body)
- )
- )
+ (&define name symbolp lambda-list stringp def-body)))
(add-hook 'edebug-setup-hook 'mode-local-setup-edebug-specs)
+(add-hook 'find-file-hook 'mode-local-post-major-mode-change)
+(add-hook 'change-major-mode-hook 'mode-local-on-major-mode-change)
+
(provide 'mode-local)
+;; arch-tag: 14b77823-f93c-4b3d-9116-495f69a6ec07
;;; mode-local.el ends here