added textile-mode and mmm-mode. xpath stuff
[emacs-init.git] / textile-mode / textile-mode.el
1 ;;; textile-mode.el --- Textile markup editing major mode
2
3 ;; Copyright (C) 2006 Free Software Foundation, Inc.
4
5 ;; Author: Julien Barnier <julien@nozav.org>
6 ;; $Id: textile-mode.el 6 2006-03-30 22:37:08Z juba $
7
8 ;; This file is free software; you can redistribute it and/or modify
9 ;; it under the terms of the GNU General Public License as published by
10 ;; the Free Software Foundation; either version 2, or (at your option)
11 ;; any later version.
12
13 ;; This file is distributed in the hope that it will be useful,
14 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
15 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 ;; GNU General Public License for more details.
17
18 ;; You should have received a copy of the GNU General Public License
19 ;; along with GNU Emacs; see the file COPYING.  If not, write to
20 ;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 ;; Boston, MA 02111-1307, USA.
22
23 ;;; Commentary:
24
25 ;; 
26
27
28 ;; Known bugs or limitations:
29
30 ;; - if several {style}, [lang] or (class) attributes are given for
31 ;;   the same block, only the first one of each type will be
32 ;;   highlighted.
33 ;;
34 ;; - some complex imbrications of inline markup and attributes are
35 ;;   not well-rendered (for example, *strong *{something}notstrong*)
36 ;;
37
38                                         
39
40 ;;; Code:
41
42
43
44 (defvar textile-mode-map
45   (let ((map (make-sparse-keymap)))
46     (define-key map [foo] 'textile-do-foo)
47     map)
48   "Keymap for `textile-mode'.")
49
50
51 (defun textile-re-concat (l)
52   "Concatenate the elements of a list with a \\| separator and
53 non-matching parentheses"
54   (concat 
55    "\\(?:"
56    (mapconcat 'identity l "\\|")
57    "\\)"))
58
59
60 (setq textile-attributes 
61       '("{[^}]*}" "([^)]*)" "\\[[^]]*\\]"))
62
63 (setq textile-blocks 
64       '("^h1" "^h2" "^h3" "^h4" "^h5" "^h6" "^p" "^bq" "^fn[0-9]+" "^#+ " "^\\*+ " "^table"))
65
66 (setq textile-inline-markup
67       '("\\*" "\\*\\*" "_" "__" "\\?\\?" "@" "-" "\\+" "^" "~" "%"))
68
69 (setq textile-alignments
70       '( "<>" "<" ">" "=" "(+" ")+"))
71
72 (setq textile-table-alignments
73       '( "<>" "<" ">" "=" "_" "\\^" "~" "\\\\[0-9]+" "/[0-9]+"))
74
75 ; from gnus-button-url-regexp
76 (setq textile-url-regexp "\\b\\(\\(www\\.\\|\\(s?https?\\|ftp\\|file\\|gopher\\|nntp\\|news\\|telnet\\|wais\\|mailto\\|info\\):\\)\\(//[-a-z0-9_.]+:[0-9]*\\)?[-a-z0-9_=!?#$@~%&*+\\/:;.,[:word:]]+[-a-z0-9_=#$@~%&*+\\/[:word:]]\\)")
77
78
79 (defun textile-block-matcher (bloc)
80   "Return the matcher regexp for a block element"
81   (concat 
82    "^"
83    bloc 
84    (textile-re-concat textile-alignments) "?" 
85    (textile-re-concat textile-attributes) "*" 
86    "\\. "
87    "\\(\\(?:.\\|\n\\)*?\\)\n\n"))
88
89 (defun textile-attribute-matcher (attr-start attr-end)
90   "Return the matcher regexp for an attribute"
91   (concat
92    (textile-re-concat (append textile-blocks textile-inline-markup))
93    (textile-re-concat textile-alignments) "*"
94    (textile-re-concat textile-attributes) "*" 
95    "\\(" attr-start "[^" 
96    (if (string-equal attr-end "\\]") "]" attr-end)
97    "]*" attr-end "\\)"))
98
99 (defun textile-inline-markup-matcher (markup)
100   "Return the matcher regexp for an inline markup"
101   (concat
102    "\\W\\(" 
103    markup
104    "\\(?:\\w\\|\\w.*?\\w\\|[[{(].*?\\w\\)"
105    markup 
106    "\\)\\W"))
107
108 (defun textile-list-bullet-matcher (bullet)
109   "Return the matcher regexp for a list bullet"
110   (concat
111    "^\\(" bullet "\\)"
112    (textile-re-concat textile-alignments) "*" 
113    (textile-re-concat textile-attributes) "*"))
114
115 (defun textile-alignments-matcher ()
116   "Return the matcher regexp for an alignments or indentation"
117   (concat
118    "\\(?:" (textile-re-concat textile-blocks) "\\|" "!" "\\)"
119    "\\(" (textile-re-concat textile-alignments) "+" "\\)"))
120
121 (defun textile-table-matcher ()
122   "Return the matcher regexp for a table row or header"
123   (concat
124    "\\(?:" 
125    "^table" (textile-re-concat textile-table-alignments) "*" (textile-re-concat textile-attributes) "*" "\\. *$" 
126    "\\|"
127    "^" (textile-re-concat textile-table-alignments) "*" (textile-re-concat textile-attributes) "*" "\\(?:\\. *|\\)"
128    "\\|"
129    "|" (textile-re-concat textile-table-alignments) "*" (textile-re-concat textile-attributes) "*" "\\(?:\\. \\)?"
130    "\\|"
131    "| *$"
132    "\\)"))
133
134 (defun textile-link-matcher ()
135   "Return the matcher regexp for a link"
136   (concat
137    "\\(?:"
138    "\\(?:" "\".*?\"" "\\|" "\\[.*?\\]" "\\)?"
139    textile-url-regexp
140    "\\|"
141    "\".*?\":[^ \n\t]+"
142    "\\)"))
143
144 (defun textile-image-matcher ()
145   "Return the matcher regexp for an image link"
146   (concat
147    "!"
148    (textile-re-concat textile-alignments) "*"
149    "/?\\w[^ \n\t]*?\\(?: *(.*?)\\|\\w\\)"
150    "!:?"))
151
152 (defun textile-acronym-matcher ()
153   "Return the matcher regexp for an acronym"
154   (concat
155    "\\w+" "(.*?)"))
156
157 (defvar textile-font-lock-keywords
158       (list
159        ;; headers
160        `(,(textile-block-matcher "h1") 1 'textile-h1-face t t)
161        `(,(textile-block-matcher "h2") 1 'textile-h2-face t t)
162        `(,(textile-block-matcher "h3") 1 'textile-h3-face t t)
163        `(,(textile-block-matcher "h4") 1 'textile-h4-face t t) 
164        `(,(textile-block-matcher "h5") 1 'textile-h5-face t t)
165        `(,(textile-block-matcher "h6") 1 'textile-h6-face t t)
166        ;; blockquotes
167        `(,(textile-block-matcher "bq") 1 'textile-blockquote-face t t)
168        ;; footnotes
169        `(,(textile-block-matcher "fn[0-9]+") 1 'textile-footnote-face t t)
170        ;; footnote marks
171        '("\\w\\([[0-9]+]\\)" 1 'textile-footnotemark-face prepend t)
172        ;; acronyms
173        `(,(textile-acronym-matcher) 0 'textile-acronym-face t t)
174
175        ;; emphasis
176        `(,(textile-inline-markup-matcher "__") 1 'textile-emph-face prepend t)
177        `(,(textile-inline-markup-matcher "_") 1 'textile-emph-face prepend t)
178        '("<em>\\(.\\|\n\\)*?</em>" 0 'textile-emph-face prepend t) 
179        ;; strength
180        `(,(textile-inline-markup-matcher "\\*\\*") 1 'textile-strong-face prepend t)
181        `(,(textile-inline-markup-matcher "\\*") 1 'textile-strong-face prepend t)
182        '("<strong>\\(.\\|\n\\)*?</strong>" 0 'textile-strong-face prepend t) 
183        ;; citation
184        `(,(textile-inline-markup-matcher "\\?\\?") 1 'textile-citation-face prepend t)
185        ;; code
186        `(,(textile-inline-markup-matcher "@") 1 'textile-code-face prepend t)
187        ;; deletion
188        `(,(textile-inline-markup-matcher "-") 1 'textile-deleted-face prepend t)
189        ;; insertion
190        `(,(textile-inline-markup-matcher "\\+") 1 'textile-inserted-face prepend t)
191        ;; superscript
192        `(,(textile-inline-markup-matcher "\\^") 1 'textile-superscript-face prepend t)
193        ;; subscript
194        `(,(textile-inline-markup-matcher "~") 1 'textile-subscript-face prepend t)
195        ;; span
196        `(,(textile-inline-markup-matcher "%") 1 'textile-span-face prepend t)
197
198        ;; image link
199        `(,(textile-image-matcher) 0 'textile-image-face t t)
200
201        ;; ordered list bullet
202        `(,(textile-list-bullet-matcher "#+") 1 'textile-ol-bullet-face)       
203        ;; unordered list bullet
204        `(,(textile-list-bullet-matcher "\\*+") 1 'textile-ul-bullet-face) 
205
206        ;; style
207        `(,(textile-attribute-matcher "{" "}") 1 'textile-style-face t t)
208        ;; class
209        `(,(textile-attribute-matcher "(" ")") 1 'textile-class-face t t)
210        ;; lang
211        `(,(textile-attribute-matcher "\\[" "\\]") 1 'textile-lang-face t t)
212
213        ;; alignments and indentation
214        `(,(textile-alignments-matcher) 1 'textile-alignments-face t t)
215
216        ;; tables
217        `(,(textile-table-matcher) 0 'textile-table-face t t)
218
219        ;; links
220        `(,(textile-link-matcher) 0 'textile-link-face t t)
221
222         ;; <pre> blocks
223        '("<pre>\\(.\\|\n\\)*?</pre>" 0 'textile-pre-face t t) 
224        ;; <code> blocks
225        '("<code>\\(.\\|\n\\)*?</code>" 0 'textile-code-face t t))
226       "Keywords/Regexp for fontlocking of textile-mode")
227
228
229 ;; (defvar textile-imenu-generic-expression
230 ;; ...)
231
232 ;; (defvar textile-outline-regexp
233 ;;   ...)
234
235
236 (define-derived-mode textile-mode text-mode "Textile"
237   "A major mode for editing textile files."
238   (set (make-local-variable 'font-lock-defaults) '(textile-font-lock-keywords t))
239   (set (make-local-variable 'font-lock-multiline) 'undecided))
240
241
242
243
244 ;; FACES
245
246 (defgroup textile-faces nil
247   "Faces used by textile-mode for syntax highlighting"
248   :group 'faces)
249
250 (defface textile-h1-face
251   '((t (:height 2.0 :weight bold)))
252   "Face used to highlight h1 headers."
253   :group 'textile-faces)
254
255 (defface textile-h2-face
256   '((t (:height 1.75 :weight bold)))
257   "Face used to highlight h2 headers."
258   :group 'textile-faces)
259
260 (defface textile-h3-face
261   '((t (:height 1.6 :weight bold)))
262   "Face used to highlight h3 headers."
263   :group 'textile-faces)
264
265 (defface textile-h4-face
266   '((t (:height 1.35 :weight bold)))
267   "Face used to highlight h4 headers."
268   :group 'textile-faces)
269
270 (defface textile-h5-face
271   '((t (:height 1.2 :weight bold)))
272   "Face used to highlight h5 headers."
273   :group 'textile-faces)
274
275 (defface textile-h6-face
276   '((t (:height 1.0 :weight bold)))
277   "Face used to highlight h6 headers."
278   :group 'textile-faces)
279
280 (defface textile-blockquote-face
281   '((t (:foreground "ivory4")))
282   "Face used to highlight bq blocks."
283   :group 'textile-faces)
284
285 (defface textile-footnote-face
286   '((t (:foreground "orange red")))
287   "Face used to highlight footnote blocks."
288   :group 'textile-faces)
289
290 (defface textile-footnotemark-face
291   '((t (:foreground "orange red")))
292   "Face used to highlight footnote marks."
293   :group 'textile-faces)
294
295 (defface textile-style-face
296   '((t (:foreground "sandy brown")))
297   "Face used to highlight style parameters."
298   :group 'textile-faces)
299
300 (defface textile-class-face
301   '((t (:foreground "yellow green")))
302   "Face used to highlight class and id parameters."
303   :group 'textile-faces)
304
305 (defface textile-lang-face
306   '((t (:foreground "sky blue")))
307   "Face used to highlight lang parameters."
308   :group 'textile-faces)
309
310 (defface textile-emph-face
311   '((t (:slant italic)))
312   "Face used to highlight emphasized words."
313   :group 'textile-faces)
314
315 (defface textile-strong-face
316   '((t (:weight bold)))
317   "Face used to highlight strong words."
318   :group 'textile-faces)
319
320 (defface textile-code-face
321   '((t (:foreground "ivory3")))
322   "Face used to highlight inline code."
323   :group 'textile-faces)
324
325 (defface textile-citation-face
326   '((t (:slant italic)))
327   "Face used to highlight citations."
328   :group 'textile-faces)
329
330 (defface textile-deleted-face
331   '((t (:strike-through t)))
332   "Face used to highlight deleted words."
333   :group 'textile-faces)
334
335 (defface textile-inserted-face
336   '((t (:underline t)))
337   "Face used to highlight inserted words."
338   :group 'textile-faces)
339
340 (defface textile-superscript-face
341   '((t (:height 1.1)))
342   "Face used to highlight superscript words."
343   :group 'textile-faces)
344
345 (defface textile-subscript-face
346   '((t (:height 0.8)))
347   "Face used to highlight subscript words."
348   :group 'textile-faces)
349
350 (defface textile-span-face
351   '((t (:foreground "pink")))
352   "Face used to highlight span words."
353   :group 'textile-faces)
354
355 (defface textile-alignments-face
356   '((t (:foreground "cyan")))
357   "Face used to highlight alignments."
358   :group 'textile-faces)
359
360 (defface textile-ol-bullet-face
361   '((t (:foreground "red")))
362   "Face used to highlight ordered lists bullets."
363   :group 'textile-faces)
364
365 (defface textile-ul-bullet-face
366   '((t (:foreground "blue")))
367   "Face used to highlight unordered list bullets."
368   :group 'textile-faces)
369
370 (defface textile-pre-face
371   '((t (:foreground "green")))
372   "Face used to highlight <pre> blocks."
373   :group 'textile-faces)
374
375 (defface textile-code-face
376   '((t (:foreground "yellow")))
377   "Face used to highlight <code> blocks."
378   :group 'textile-faces)
379
380 (defface textile-table-face
381   '((t (:foreground "red")))
382   "Face used to highlight tables."
383   :group 'textile-faces)
384
385 (defface textile-link-face
386   '((t (:foreground "blue")))
387   "Face used to highlight links."
388   :group 'textile-faces)
389
390 (defface textile-image-face
391   '((t (:foreground "pink")))
392   "Face used to highlight image links."
393   :group 'textile-faces)
394
395 (defface textile-acronym-face
396   '((t (:foreground "cyan")))
397   "Face used to highlight acronyms links."
398   :group 'textile-faces)
399
400
401 (provide 'textile-mode)
402  ;;; textile-mode.el ends here