123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302 |
- ;;; multi-mode.el --- Allowing multiple major modes in a buffer.
- ;;;****************************************************************************
- ;;; $Id: multi-mode.el,v 1.2 2002/11/15 09:33:50 marmotte Exp $
- ;;;****************************************************************************
- ;;
- ;;
- ;; 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 2002/11/15 09:33:50 marmotte
- ;;
- ;; * Make most of the config compile
- ;;
- ;; Revision 1.1 2002/11/14 08:36:38 marmotte
- ;; * Changed load of file, to load-path, so that the config files are not
- ;; always loaded.
- ;; * Added multi-mode to the emacs config
- ;; * Added support for php and jsp, throught multi-mode.
- ;; - Still need to add a version of c++-mode for php, cause somethings are
- ;; not really well handled...
- ;;
- ; 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
- ;; Vdenburger 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.|
- ;; 11-Jun-1994|1.2|~/misc/multi-mode.el.Z|
- ;;*****************************************************************************
- ;;
- ;; 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)
|