123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302 |
- (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.")
- (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)
- (> (prefix-numeric-value arg) 0)))
- (let ((ok t)
- (tt transitions)
- trans)
- (while tt
- (setq trans (car tt)
- tt (cdr tt))
- (if (or (not (listp trans))
- (not (stringp (first trans)))
- (not (symbolp (second trans))))
- (setq ok nil
- tt nil))
- )
- (if (and ok
- initial-mode
- (symbolp initial-mode))
- (setq multi-mode-transitions
- (cons initial-mode transitions)))
- )
- (force-mode-line-update)
- )
- (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."
-
-
-
- (if (and multi-mode
- multi-mode-transitions
- (eval (cons 'and multi-mode-beware))
- )
- (let* ((transition (cdr multi-mode-transitions))
- (mode (car multi-mode-transitions))
- (mode-function mode)
- (pos -1)
- hit
- tt)
- (while transition
- (setq tt (car transition)
- transition (cdr transition))
- (setq hit (save-excursion
- (if (search-backward
- (first tt)
- nil
- t)
- (point)
- -2)))
- (if (> hit pos)
- (setq pos hit
- mode (second tt)
- mode-function (or (third tt) mode))
- )
- )
- (if (not (equal major-mode mode))
- (let ((transitions multi-mode-transitions))
- (if (fboundp mode-function)
- (funcall mode-function))
- (setq multi-mode-transitions transitions
- multi-mode t)))
- )
- )
- )
- (add-hook 'post-command-hook 'multi-mode-update-mode)
- (provide 'multi-mode)
|