| 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 tot 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 argumentis positive.Sometimes it is desirable to have different major modes in one buffer.  Onesuch case occurs  when editing comments  in a programming  language buffer.Here it  might be desirable  to use a totally  different mode  than the oneused for editing the program code itself.It is desirable   to use different  modes  instead  of enhancing one   modebecause much effort has  already been put  in various modes which needs notto 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  certaintokens (i.e.  transition  strings)  indicate  the places  where a  new modeshould be entered.  To determine  the mode at a point  it is only necessaryto find the last transition string before point.The desired modes are described in a list of pairs or triples consisting ofa transition string and  a mode (a  symbol).  Optionally a function  symbolcan   be specified   which  is evaluated  to   activate  the desired  mode.Additionally the mode in absence of preceding transition  strings has to bespecified.When called not interactively there are additional arguments to specify thetransitions.INITIAL-MODE  is a symbol denoting   a major mode   to  be used before  anytransition 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 activatethe mode MODE specified in the second argument. Optionally a third argumentcan  be given. The  symbol FUNCTION is  used as a function  to be called toturn 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 argumentdeclares the default mode to be c-mode. Thus at the beginning of the bufferc-mode is turned on. If a '/*'  is found before point then fundamental-modemay 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 isused depends on the last activating  pattern before point.  In this exampleeverything between /* and */ can be edited  in fundamental mode. Everythingelse 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)
 |