diff options
Diffstat (limited to 'support/iso-tex/multi-mode.el')
-rw-r--r-- | support/iso-tex/multi-mode.el | 288 |
1 files changed, 288 insertions, 0 deletions
diff --git a/support/iso-tex/multi-mode.el b/support/iso-tex/multi-mode.el new file mode 100644 index 0000000000..48c9746178 --- /dev/null +++ b/support/iso-tex/multi-mode.el @@ -0,0 +1,288 @@ +;;; multi-mode.el --- Allowing multiple major modes in a buffer. +;;;**************************************************************************** +;;; $Id: multi-mode.el,v 1.2 1994/06/11 22:08:22 gerd Exp gerd $ +;;;**************************************************************************** +;; +;; +;; Description: +;; +;; Sometimes it is desirable to have different major modes in one +;; buffer. One such case occurs when editing comments in a +;; programming language buffer. Here it might be desirable to use a +;; totally different mode than the one used for editing the program +;; code itself. +;; +;; I have adoped this practice for editing Prolog. The code itself is +;; edited in prolog-mode, whereas the comments are edited in +;; LaTeX-mode. +;; +;; It is desirable to use different modes instead of enhancing one +;; mode because much efford has already been put in various modes +;; which needs not to be duplicated. +;; +;; The multi-mode minor mode provides a means to accomplish such a +;; feature. +;; +;; The modes are described by initializing strings. I assume that +;; certain tokens (i.e. transition strings) indicate the places where +;; a new mode should be entered. To determine the mode at a point it +;; is only neccessary to find the last transition string before point. +;; +;; The desired modes are described in a list of pairs or triples +;; consisting of a transition string and a mode (a symbol). +;; Optionally a function symbol can be specified which is evaluated to +;; activate the desired mode. Additionally the mode in absence of +;; preceding transition strings has to be specified. +;; +;; +;; +;; +;; Installation: +;; 1. Ensure that multi-mode.el is on the load-path. +;; 2. For efficiency it might be desirable to byte-compile +;; multi-mode.el. +;; 3. Put the following in your .emacs file or a similar place +;; where it is loaded when needed. +;; +;; (autoload 'multi-mode +;; "multi-mode" +;; "Allowing multiple major modes in a buffer." +;; t) +;; +;; 4. Define your own incarnation of multi mode to serve as major +;; mode. This can be done in your .emacs file. E.g. +;; +;; (defun multi-c-fundamental-mode () (interactive) +;; (multi-mode 1 +;; 'c-mode +;; '(\"/*\" fundamental-mode my-fundamental-setup) +;; '(\"*/\" c-mode))) +;; +;; This major mode can now be used to turn on the multi-mode in the +;; minibuffer, or in the auto-mode-alist, or in the local variables +;; of a file. E.g. +;; +;; (setq auto-mode-alist +;; (cons '("\\.[ch]$" . multi-c-fundamental-mode) +;; auto-mode-alist) +;; +;; +;; Bugs and Problems: +;; - It is rather easy to hang my whole workstation when +;; multi-mode-transitions has not a proper value. +;; For sake of efficiency I omit finer type checking to avoid this +;; problem. +;; CURE: Never try to change the variable yourself. Use the +;; function multi-mode instead. +;; +;; To do: +;; - The generalization of transition strings to regular expressions +;; seems to be straight forward. For efficience reasons I will do it +;; only upon request. +;; +;; - No provisions have been made to make the key bindings accessible +;; in all modes. This might be desirable. +;; +;; +;; Changes: +;; $Log: multi-mode.el,v $ +; Revision 1.2 1994/06/11 22:08:22 gerd +; *** empty log message *** +; +; Revision 1.1 1994/05/24 12:41:30 gerd +; A little hack has been enhanced to a minor mode. +;; +;; +;; Author: +;; Gerd Neugebauer +;; Ödenburger Str. 16 +;; 64295 Darmstadt (Germany) +;; +;; Net: gerd@intellektik.informatik.th-darmstadt.de +;; gerd@imn.th-leipzig.de +;; +;;***************************************************************************** +;; LCD Archive Entry: +;; multi-mode|Gerd Neugebauer|gerd@intellektik.informatik.th-darmstadt.de| +;; Minor mode allowing multiple major modes in a single buffer.| +;; $Date: 1994/06/11 22:08:22 $|$Revision: 1.2 $|| +;;***************************************************************************** +;; +;; Copyright (C) 1994 Gerd Neugebauer +;; +;; multi-mode.el is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY. No author or distributor +;; accepts responsibility to anyone for the consequences of using it +;; or for whether it serves any particular purpose or works at all, +;; unless he says so in writing. Refer to the GNU General Public +;; License for full details. +;; +;; Everyone is granted permission to copy, modify and redistribute +;; multi-mode.el, but only under the conditions described in the +;; GNU General Public License. A copy of this license is +;; supposed to have been given to you along with GNU Emacs so you +;; can know your rights and responsibilities. It should be in a +;; file named COPYING. Among other things, the copyright notice +;; and this notice must be preserved on all copies. +;; + +;;;---------------------------------------------------------------------------- +;;; Variable definitions and initializations + +(make-variable-buffer-local 'multi-mode-transitions) +(defvar multi-mode-transitions nil + "Transition definition for the multi-mode minor mode. +") + +(defvar multi-mode-beware '( (not isearch-mode) ) + "List of forms to check if multi-mode is desirable. If all forms evaluate to +t then a mode switch is allowed.") + +(make-variable-buffer-local 'multi-mode) +(defvar multi-mode nil + "This variable indicates if the multi-mode minor mode is active.") + + +;;;---------------------------------------------------------------------------- +;;; Definition of the minor mode + +(defun multi-mode (&optional arg &optional initial-mode &rest transitions) + "Allowing multiple major modes in a buffer. + +Toggle multi mode. With numeric argument turn on multi mode if the argument +is positive. + +Sometimes it is desirable to have different major modes in one buffer. One +such case occurs when editing comments in a programming language buffer. +Here it might be desirable to use a totally different mode than the one +used for editing the program code itself. + +It is desirable to use different modes instead of enhancing one mode +because much effort has already been put in various modes which needs not +to be duplicated. + +The multi-mode minor mode provides a means to accomplish such a feature. + +The modes are described by initializing strings. I assume that certain +tokens (i.e. transition strings) indicate the places where a new mode +should be entered. To determine the mode at a point it is only necessary +to find the last transition string before point. + +The desired modes are described in a list of pairs or triples consisting of +a transition string and a mode (a symbol). Optionally a function symbol +can be specified which is evaluated to activate the desired mode. +Additionally the mode in absence of preceding transition strings has to be +specified. + +When called not interactively there are additional arguments to specify the +transitions. + +INITIAL-MODE is a symbol denoting a major mode to be used before any +transition strings are present before point. + +The remaining optional arguments are pairs + (TOKEN MODE) +or triples + (TOKEN MODE FUNCTION) + +The first element TOKEN is a string which indicates the token to activate +the mode MODE specified in the second argument. Optionally a third argument +can be given. The symbol FUNCTION is used as a function to be called to +turn on the mode given as second argument. It defaults to MODE. + +Consider the following example: + +(multi-mode 1 + c-mode + (\"/*\" fundamental-mode my-fundamental-setup) + (\"*/\" c-mode)) + +The first argument forces multi-mode to be turned on. The second argument +declares the default mode to be c-mode. Thus at the beginning of the buffer +c-mode is turned on. If a '/*' is found before point then fundamental-mode +may be turned on. This is done using the function my-fundamental-setup. + +If a '*/' is found before point then c-mode may be activated. Which mode is +used depends on the last activating pattern before point. In this example +everything between /* and */ can be edited in fundamental mode. Everything +else is in c-mode. + +See also the documentation of multi-mode-beware." + (interactive "P") + (setq multi-mode ; + (if (null arg) (not multi-mode) ; Toggle multi-mode if no arg + (> (prefix-numeric-value arg) 0))) ; otherwise turn it on or off + (let ((ok t) ; result of type check + (tt transitions) ; transition table + trans) ; transition + (while tt ; Check the transition table + (setq trans (car tt) ; Get a single transition + tt (cdr tt)) ; Advance the table pointer + (if (or (not (listp trans)) ; Check the transition + (not (stringp (first trans))) ; + (not (symbolp (second trans)))) ; + (setq ok nil ; set error mark + tt nil)) ; stop checking + ) + (if (and ok ; if transition table is ok + initial-mode ; check the initial-mode + (symbolp initial-mode)) ; + (setq multi-mode-transitions ; set the local variable + (cons initial-mode transitions))) ; + ) + + (force-mode-line-update) ; show the new state +) + +(or (assq 'multi-mode minor-mode-alist) + (setq minor-mode-alist (cons '(multi-mode " MULTI") minor-mode-alist))) + + +(defun multi-mode-update-mode () + "Perform a mode switch if multi-mode is active." + ;; This function only starts to work if multi mode is on + ;; and a transition table is defined. Additionally the forms in + ;; multi-mode-beware are evaluated to see if a mode switch is desirable. + (if (and multi-mode + multi-mode-transitions + (eval (cons 'and multi-mode-beware)) + ) + (let* ((transition (cdr multi-mode-transitions)) ; get transitions + (mode (car multi-mode-transitions)) ; get initial mode + (mode-function mode) ; set initial mode switching function + (pos -1) ; set the initial position of a transit + hit ; new position of a transition string + tt) ; transition table + (while transition + (setq tt (car transition) ; extract a single transition + transition (cdr transition)) ; advance the transitions + (setq hit (save-excursion ; we don't want to change point + (if (search-backward ; unfailing backward search + (first tt) ; for the transition pattern + nil + t) + (point) ; upon sucess use the position + -2))) ; otherwise try to ignore it + (if (> hit pos) ; pattern is newer than prev. + (setq pos hit ; then save position + mode (second tt) ; the desired mode and an + mode-function (or (third tt) mode)); optional function + ) + ) + (if (not (equal major-mode mode)) ; if mode needs switching + (let ((transitions multi-mode-transitions)) ; save transition table + (if (fboundp mode-function) ; if mode function is defined + (funcall mode-function)) ; then call it + (setq multi-mode-transitions transitions ; restore transition + multi-mode t))) ; and minor mode + ) + ) +) + +;;;---------------------------------------------------------------------------- +;;; The function is hooked into the post-command-hook to be called after +;;; each function. +;;; +(add-hook 'post-command-hook 'multi-mode-update-mode) + +(provide 'multi-mode) |