added textile-mode and mmm-mode. xpath stuff
[emacs-init.git] / mmm-mode-0.4.8 / mmm-sample.el
1 ;;; mmm-sample.el --- Sample MMM submode classes
2
3 ;; Copyright (C) 2003, 2004 by Michael Abraham Shulman
4
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 $
7
8 ;;{{{ GPL
9
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)
13 ;; any later version.
14
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.
19
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.
24
25 ;;}}}
26
27 ;;; Commentary:
28
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'.
31
32 ;;; Code:
33
34 (require 'mmm-auto)
35 (require 'mmm-vars)
36
37 ;;{{{ CSS embedded in HTML
38
39 ;; This is the simplest example. Many applications will need no more
40 ;; than a simple regexp.
41 (mmm-add-classes
42  '((embedded-css
43     :submode css
44     :face mmm-declaration-submode-face
45     :delimiter-mode nil
46     :front "<style[^>]*>"
47     :back "</style>")))
48
49 ;;}}}
50 ;;{{{ Javascript in HTML
51
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.
55 (mmm-add-group
56  'html-js
57  '((js-tag
58     :submode javascript
59     :face mmm-code-submode-face
60     :delimiter-mode nil
61     :front "<script\[^>\]*\\(language=\"javascript\\([0-9.]*\\)\"\\|type=\"text/javascript\"\\)\[^>\]*>"
62     :back"</script>"
63     :insert ((?j js-tag nil @ "<script language=\"JavaScript\">"
64                  @ "\n" _ "\n" @ "</script>" @))
65     )
66    (js-inline
67     :submode javascript
68     :face mmm-code-submode-face
69     :delimiter-mode nil
70     :front "on\\w+=\""
71     :back "\"")))
72
73 ;;}}}
74 ;;{{{ Here-documents
75
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
82 ;; underscores.
83
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.")
92
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.
104              (intern
105               (mapconcat #'identity
106                          (nconc (ldiff words (member "mode" words))
107                                 (list "mode"))
108                          "-")))
109             ;; Try each word by itself (preference list)
110             (some #'(lambda (word)
111                       (mmm-ensure-modename (intern word)))
112                   words)
113             ;; Try each word with -mode tacked on
114             (some #'(lambda (word)
115                       (mmm-ensure-modename
116                        (intern (concat word "-mode"))))
117                   words)
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")))
122                   return it)
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)))))
128
129 (mmm-add-classes
130  '((here-doc
131     :front "<<[\"\'\`]?\\([a-zA-Z0-9_-]+\\)"
132     :front-offset (end-of-line 1)
133     :back "^~1$"
134     :save-matches 1
135     :delimiter-mode nil
136     :match-submode mmm-here-doc-get-mode
137     :insert ((?d here-doc "Here-document Name: " @ "<<" str _ "\n"
138                  @ "\n" @ str "\n" @))
139     )))
140
141 ;;}}}
142 ;;{{{ Embperl
143
144 (mmm-add-group
145  'embperl
146  '((embperl-perl
147     :submode perl
148     :front "\\[\\([-\\+!\\*\\$]\\)"
149     :back "~1\\]"
150     :save-matches 1
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 . "$")
164              )
165     )
166    (embperl-comment
167     :submode text-mode
168     :face mmm-comment-submode-face
169     :front "\\[#"
170     :back "#\\]"
171     :insert ((?# embperl-comment nil @ "[#" @ " " _ " " @ "#]" @))
172     )))
173
174 ;;}}}
175 ;;{{{ ePerl
176
177 (mmm-add-group
178  'eperl
179  '((eperl-expr
180     :submode perl
181     :face mmm-output-submode-face
182     :front "<:="
183     :back ":>"
184     :insert ((?= eperl-expr nil @ "<:=" @ " " _ " " @ ":>" @)))
185    (eperl-code
186     :submode perl
187     :face mmm-code-submode-face
188     :front "<:"
189     :back "_?:>"
190     :match-name "eperl"
191     :insert ((?p eperl-code nil @ "<:" @ " " _ " " @ ":>" @)
192              (?: eperl-code ?p . nil)
193              (?_ eperl-code_ nil @ "<:" @ " " _ " " @ "_:>" @)))
194    (eperl-comment
195     :submode text
196     :face mmm-comment-submode-face
197     :front ":>//"
198     :back "\n")
199    ))
200
201 ;;}}}
202 ;;{{{ File Variables
203
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'.
207
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.
212   (let ((bounds
213          (save-excursion
214            (save-match-data
215              (goto-char (point-max))
216              (backward-page)
217              (and (re-search-forward "^\\(.*\\)Local Variables:" nil t)
218                   (list (match-string 1)
219                         (progn (end-of-line) (point))
220                         (and (search-forward
221                               (format "%sEnd:" (match-string 1))
222                               nil t)
223                              (progn (beginning-of-line)
224                                     (point)))))))))
225     (and bounds (caddr bounds)
226          (save-match-data
227            (string-match (format "^%s" (regexp-quote (car bounds)))
228                          (match-string 0)))
229          (> (match-beginning 0) (cadr bounds))
230          (< (match-end 0) (caddr bounds)))))
231
232 (defun mmm-file-variables-find-back (bound)
233   (forward-sexp)
234   (if (> (point) bound)
235       nil
236     (looking-at "")))
237
238 (mmm-add-classes
239  '((file-variables
240     :front ".+:"
241     :front-verify mmm-file-variables-verify
242     :back mmm-file-variables-find-back
243     :submode emacs-lisp-mode
244     :delimiter-mode nil
245     )))
246
247 ;;}}}
248 ;;{{{ JSP Pages
249
250 (mmm-add-group 'jsp
251  `((jsp-comment
252     :submode text-mode
253     :face mmm-comment-submode-face
254     :front "<%--"
255     :back "--%>"
256     :insert ((?- jsp-comment nil @ "<%--" @ " " _ " " @ "--%>" @))
257     )
258    (jsp-code
259     :submode java
260     :match-face (("<%!" . mmm-declaration-submode-face)
261                  ("<%=" . mmm-output-submode-face)
262                  ("<%"  . mmm-code-submode-face))
263     :front "<%[!=]?"
264     :back "%>"
265     :match-name "jsp"
266     :insert ((?% jsp-code nil @ "<%" @ " " _ " " @ "%>" @)
267              (?! jsp-declaration nil @ "<%!" @ " " _ " " @ "%>" @)
268              (?= jsp-expression nil @ "<%=" @ " " _ " " @ "%>" @))
269     )
270    (jsp-directive
271     :submode text-mode
272     :face mmm-special-submode-face
273     :front "<%@"
274     :back "%>"
275     :insert ((?@ jsp-directive nil @ "<%@" @ " " _ " " @ "%>" @))
276     )))
277
278 ;;}}}
279 ;;{{{ SGML DTD
280
281 ;; Thanks to Yann Dirson <ydirson@fr.alcove.com> for writing and
282 ;; contributing this submode class.
283
284 (mmm-add-classes
285  '((sgml-dtd
286     :submode dtd-mode
287     :face mmm-declaration-submode-face
288     :delimiter-mode nil
289     :front "<! *doctype[^>[]*\\["
290     :back "]>")))
291
292 ;;}}}
293 ;;{{{ <Perl> in httpd.conf
294
295 (mmm-add-classes
296  '((httpd-conf-perl
297     :submode perl
298     :delimiter-mode nil
299     :front "<Perl>"
300     :back "</Perl>")))
301
302 ;; Suggested Use:
303 ;; (mmm-add-mode-ext-class 'apache-generic-mode nil 'httpd-conf-perl)
304
305 ;;}}}
306 ;;{{{ PHP in HTML
307
308 (mmm-add-group 'html-php
309  '((html-php-output
310     :submode php-mode
311     :face mmm-output-submode-face
312     :front "<\\?php *echo "
313     :back "\\?>"
314     :include-front t
315     :front-offset 5
316     :insert ((?e php-echo nil @ "<?php" @ " echo " _ " " @ "?>" @))
317     )
318    (html-php-code
319     :submode php-mode
320     :face mmm-code-submode-face
321     :front "<\\?\\(php\\)?"
322     :back "\\?>"
323     :insert ((?p php-section nil @ "<?php" @ " " _ " " @ "?>" @)
324              (?b php-block nil @ "<?php" @ "\n" _ "\n" @ "?>" @))
325     )))
326
327 ;;}}}
328
329 ;; NOT YET UPDATED
330 ;;{{{ HTML in PL/SQL;-COM-
331 ;-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.
339 ;-COM-
340 ;-COM-;; These functions have not been thoroughly tested, and always search
341 ;-COM-;; the entire buffer, ignoring START and END.
342 ;-COM-
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)))))
351 ;-COM-
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)))))
366 ;-COM-
367 ;-COM-(add-to-list 'mmm-classes-alist
368 ;-COM-  '(htp-p (:function html-mode mmm-html-in-plsql)))
369 ;-COM-
370 ;;}}}
371
372 (provide 'mmm-sample)
373
374 ;;; mmm-sample.el ends here