summaryrefslogtreecommitdiff
path: root/support/iso-tex/multi-mode.el
diff options
context:
space:
mode:
Diffstat (limited to 'support/iso-tex/multi-mode.el')
-rw-r--r--support/iso-tex/multi-mode.el288
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)