1 ;;; mmm-sample.el --- Sample MMM submode classes
3 ;; Copyright (C) 2003, 2004 by Michael Abraham Shulman
5 ;; Author: Michael Abraham Shulman <viritrilbia@users.sourceforge.net>
6 ;; Version: $Id: mmm-sample.el,v 1.28 2004/06/03 00:53:52 alanshutko Exp $
10 ;; This file is free software; you can redistribute it and/or modify
11 ;; it under the terms of the GNU General Public License as published by
12 ;; the Free Software Foundation; either version 2, or (at your option)
15 ;; This file is distributed in the hope that it will be useful,
16 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 ;; GNU General Public License for more details.
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GNU Emacs; see the file COPYING. If not, write to
22 ;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23 ;; Boston, MA 02111-1307, USA.
29 ;; This file contains several sample submode classes for use with MMM
30 ;; Mode. For a more detailed and useful example, see `mmm-mason.el'.
37 ;;{{{ CSS embedded in HTML
39 ;; This is the simplest example. Many applications will need no more
40 ;; than a simple regexp.
44 :face mmm-declaration-submode-face
50 ;;{{{ Javascript in HTML
52 ;; We use two classes here, one for code in a <script> tag and another
53 ;; for code embedded as a property of an HTML tag, then another class
54 ;; to group them together.
59 :face mmm-code-submode-face
61 :front "<script\[^>\]*\\(language=\"javascript\\([0-9.]*\\)\"\\|type=\"text/javascript\"\\)\[^>\]*>"
63 :insert ((?j js-tag nil @ "<script language=\"JavaScript\">"
64 @ "\n" _ "\n" @ "</script>" @))
68 :face mmm-code-submode-face
76 ;; Here we match the here-document syntax used by Perl and shell
77 ;; scripts. We try to be automagic about recognizing what mode the
78 ;; here-document should be in. To make sure that it is recognized
79 ;; correctly, the name of the mode, perhaps minus `-mode', in upper
80 ;; case, and/or with hyphens converted to underscores, should be
81 ;; separated from the rest of the here-document name by hyphens or
84 (defvar mmm-here-doc-mode-alist '()
85 "Alist associating here-document name regexps to submodes.
86 Normally, this variable is unnecessary, as the `here-doc' submode
87 class tries to automagically recognize the right submode. If you use
88 here-document names that it doesn't recognize, however, then you can
89 add elements to this alist. Each element is \(REGEXP . MODE) where
90 REGEXP is a regular expression matched against the here-document name
91 and MODE is a major mode function symbol.")
93 (defun mmm-here-doc-get-mode (string)
94 (string-match "[a-zA-Z_-]+" string)
95 (setq string (match-string 0 string))
96 (or (mmm-ensure-modename
97 ;; First try the user override variable.
98 (some #'(lambda (pair)
99 (if (string-match (car pair) string) (cdr pair) nil))
100 mmm-here-doc-mode-alist))
101 (let ((words (split-string (downcase string) "[_-]+")))
102 (or (mmm-ensure-modename
103 ;; Try the whole name, stopping at "mode" if present.
105 (mapconcat #'identity
106 (nconc (ldiff words (member "mode" words))
109 ;; Try each word by itself (preference list)
110 (some #'(lambda (word)
111 (mmm-ensure-modename (intern word)))
113 ;; Try each word with -mode tacked on
114 (some #'(lambda (word)
116 (intern (concat word "-mode"))))
118 ;; Try each pair of words with -mode tacked on
119 (loop for (one two) on words
120 if (mmm-ensure-modename
121 (intern (concat one two "-mode")))
123 ;; I'm unaware of any modes whose names, minus `-mode',
124 ;; are more than two words long, and if the entire mode
125 ;; name (perhaps minus `-mode') doesn't occur in the
126 ;; here-document name, we can give up.
127 (signal 'mmm-no-matching-submode nil)))))
131 :front "<<[\"\'\`]?\\([a-zA-Z0-9_-]+\\)"
132 :front-offset (end-of-line 1)
136 :match-submode mmm-here-doc-get-mode
137 :insert ((?d here-doc "Here-document Name: " @ "<<" str _ "\n"
138 @ "\n" @ str "\n" @))
148 :front "\\[\\([-\\+!\\*\\$]\\)"
151 :match-name "embperl"
152 :match-face (("[+" . mmm-output-submode-face)
153 ("[-" . mmm-code-submode-face)
154 ("[!" . mmm-init-submode-face)
155 ("[*" . mmm-code-submode-face)
156 ("[$" . mmm-special-submode-face))
157 :insert ((?p embperl "Region Type (Character): " @ "[" str
158 @ " " _ " " @ str "]" @)
159 (?+ embperl+ ?p . "+")
160 (?- embperl- ?p . "-")
161 (?! embperl! ?p . "!")
162 (?* embperl* ?p . "*")
163 (?$ embperl$ ?p . "$")
168 :face mmm-comment-submode-face
171 :insert ((?# embperl-comment nil @ "[#" @ " " _ " " @ "#]" @))
181 :face mmm-output-submode-face
184 :insert ((?= eperl-expr nil @ "<:=" @ " " _ " " @ ":>" @)))
187 :face mmm-code-submode-face
191 :insert ((?p eperl-code nil @ "<:" @ " " _ " " @ ":>" @)
192 (?: eperl-code ?p . nil)
193 (?_ eperl-code_ nil @ "<:" @ " " _ " " @ "_:>" @)))
196 :face mmm-comment-submode-face
204 ;; This submode class puts file local variable values, specified with
205 ;; a `Local Variables:' line as in (emacs)File Variables, into Emacs
206 ;; Lisp Mode. It is a good candidate to put in `mmm-global-classes'.
208 (defun mmm-file-variables-verify ()
209 ;; It would be nice to cache this somehow, which could be done in a
210 ;; buffer-local variable with markers for positions, but the trick
211 ;; is knowing when to expire the cache.
215 (goto-char (point-max))
217 (and (re-search-forward "^\\(.*\\)Local Variables:" nil t)
218 (list (match-string 1)
219 (progn (end-of-line) (point))
221 (format "%sEnd:" (match-string 1))
223 (progn (beginning-of-line)
225 (and bounds (caddr bounds)
227 (string-match (format "^%s" (regexp-quote (car bounds)))
229 (> (match-beginning 0) (cadr bounds))
230 (< (match-end 0) (caddr bounds)))))
232 (defun mmm-file-variables-find-back (bound)
234 (if (> (point) bound)
241 :front-verify mmm-file-variables-verify
242 :back mmm-file-variables-find-back
243 :submode emacs-lisp-mode
253 :face mmm-comment-submode-face
256 :insert ((?- jsp-comment nil @ "<%--" @ " " _ " " @ "--%>" @))
260 :match-face (("<%!" . mmm-declaration-submode-face)
261 ("<%=" . mmm-output-submode-face)
262 ("<%" . mmm-code-submode-face))
266 :insert ((?% jsp-code nil @ "<%" @ " " _ " " @ "%>" @)
267 (?! jsp-declaration nil @ "<%!" @ " " _ " " @ "%>" @)
268 (?= jsp-expression nil @ "<%=" @ " " _ " " @ "%>" @))
272 :face mmm-special-submode-face
275 :insert ((?@ jsp-directive nil @ "<%@" @ " " _ " " @ "%>" @))
281 ;; Thanks to Yann Dirson <ydirson@fr.alcove.com> for writing and
282 ;; contributing this submode class.
287 :face mmm-declaration-submode-face
289 :front "<! *doctype[^>[]*\\["
293 ;;{{{ <Perl> in httpd.conf
303 ;; (mmm-add-mode-ext-class 'apache-generic-mode nil 'httpd-conf-perl)
308 (mmm-add-group 'html-php
311 :face mmm-output-submode-face
312 :front "<\\?php *echo "
316 :insert ((?e php-echo nil @ "<?php" @ " echo " _ " " @ "?>" @))
320 :face mmm-code-submode-face
321 :front "<\\?\\(php\\)?"
323 :insert ((?p php-section nil @ "<?php" @ " " _ " " @ "?>" @)
324 (?b php-block nil @ "<?php" @ "\n" _ "\n" @ "?>" @))
330 ;;{{{ HTML in PL/SQL;-COM-
332 ;-COM-;; This one is the most complex example. In PL/SQL, HTML is generally
333 ;-COM-;; output as a (single quote delimited) string inside a call to htp.p or
334 ;-COM-;; its brethren. The problem is that there may be strings outside of
335 ;-COM-;; htp.p calls that should not be HTML, so we need to only look inside
336 ;-COM-;; these calls. The situation is complicated by PL/SQL's rule that two
337 ;-COM-;; sequential single quotes in a string mean to put a single quote
338 ;-COM-;; inside the string.
340 ;-COM-;; These functions have not been thoroughly tested, and always search
341 ;-COM-;; the entire buffer, ignoring START and END.
343 ;-COM-(defun mmm-html-in-plsql (start end)
344 ;-COM- (save-match-data
345 ;-COM- (let ((case-fold-search t))
346 ;-COM- (and (re-search-forward "htp.p\\(\\|rn\\|rint\\)1?(" nil t)
347 ;-COM- (mmm-html-in-plsql-in-htp
348 ;-COM- ;; Find the end of the procedure call
349 ;-COM- (save-excursion (forward-char -1) (forward-sexp) (point))
350 ;-COM- start end)))))
352 ;-COM-(defun mmm-html-in-plsql-in-htp (htp-end start end)
353 ;-COM- (let (beg end)
354 ;-COM- (or (and (re-search-forward "'" htp-end 'limit)
355 ;-COM- (setf beg (match-end 0))
356 ;-COM- ;; Find an odd number of 's to end the string.
357 ;-COM- (do ((lgth 0 (length (match-string 0))))
358 ;-COM- ((oddp lgth) t)
359 ;-COM- (re-search-forward "'+" nil t))
360 ;-COM- (setf end (1- (match-end 0)))
361 ;-COM- (cons (cons beg end)
362 ;-COM- (mmm-html-in-plsql-in-htp htp-end start end)))
363 ;-COM- ;; No more strings in the procedure call; look for another.
364 ;-COM- (and (eql (point) htp-end)
365 ;-COM- (mmm-html-in-plsql start end)))))
367 ;-COM-(add-to-list 'mmm-classes-alist
368 ;-COM- '(htp-p (:function html-mode mmm-html-in-plsql)))
372 (provide 'mmm-sample)
374 ;;; mmm-sample.el ends here