1 ;;; textile-mode.el --- Textile markup editing major mode
3 ;; Copyright (C) 2006 Free Software Foundation, Inc.
5 ;; Author: Julien Barnier <julien@nozav.org>
6 ;; $Id: textile-mode.el 6 2006-03-30 22:37:08Z juba $
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)
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.
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.
28 ;; Known bugs or limitations:
30 ;; - if several {style}, [lang] or (class) attributes are given for
31 ;; the same block, only the first one of each type will be
34 ;; - some complex imbrications of inline markup and attributes are
35 ;; not well-rendered (for example, *strong *{something}notstrong*)
44 (defvar textile-mode-map
45 (let ((map (make-sparse-keymap)))
46 (define-key map [foo] 'textile-do-foo)
48 "Keymap for `textile-mode'.")
51 (defun textile-re-concat (l)
52 "Concatenate the elements of a list with a \\| separator and
53 non-matching parentheses"
56 (mapconcat 'identity l "\\|")
60 (setq textile-attributes
61 '("{[^}]*}" "([^)]*)" "\\[[^]]*\\]"))
64 '("^h1" "^h2" "^h3" "^h4" "^h5" "^h6" "^p" "^bq" "^fn[0-9]+" "^#+ " "^\\*+ " "^table"))
66 (setq textile-inline-markup
67 '("\\*" "\\*\\*" "_" "__" "\\?\\?" "@" "-" "\\+" "^" "~" "%"))
69 (setq textile-alignments
70 '( "<>" "<" ">" "=" "(+" ")+"))
72 (setq textile-table-alignments
73 '( "<>" "<" ">" "=" "_" "\\^" "~" "\\\\[0-9]+" "/[0-9]+"))
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:]]\\)")
79 (defun textile-block-matcher (bloc)
80 "Return the matcher regexp for a block element"
84 (textile-re-concat textile-alignments) "?"
85 (textile-re-concat textile-attributes) "*"
87 "\\(\\(?:.\\|\n\\)*?\\)\n\n"))
89 (defun textile-attribute-matcher (attr-start attr-end)
90 "Return the matcher regexp for an attribute"
92 (textile-re-concat (append textile-blocks textile-inline-markup))
93 (textile-re-concat textile-alignments) "*"
94 (textile-re-concat textile-attributes) "*"
96 (if (string-equal attr-end "\\]") "]" attr-end)
99 (defun textile-inline-markup-matcher (markup)
100 "Return the matcher regexp for an inline markup"
104 "\\(?:\\w\\|\\w.*?\\w\\|[[{(].*?\\w\\)"
108 (defun textile-list-bullet-matcher (bullet)
109 "Return the matcher regexp for a list bullet"
112 (textile-re-concat textile-alignments) "*"
113 (textile-re-concat textile-attributes) "*"))
115 (defun textile-alignments-matcher ()
116 "Return the matcher regexp for an alignments or indentation"
118 "\\(?:" (textile-re-concat textile-blocks) "\\|" "!" "\\)"
119 "\\(" (textile-re-concat textile-alignments) "+" "\\)"))
121 (defun textile-table-matcher ()
122 "Return the matcher regexp for a table row or header"
125 "^table" (textile-re-concat textile-table-alignments) "*" (textile-re-concat textile-attributes) "*" "\\. *$"
127 "^" (textile-re-concat textile-table-alignments) "*" (textile-re-concat textile-attributes) "*" "\\(?:\\. *|\\)"
129 "|" (textile-re-concat textile-table-alignments) "*" (textile-re-concat textile-attributes) "*" "\\(?:\\. \\)?"
134 (defun textile-link-matcher ()
135 "Return the matcher regexp for a link"
138 "\\(?:" "\".*?\"" "\\|" "\\[.*?\\]" "\\)?"
144 (defun textile-image-matcher ()
145 "Return the matcher regexp for an image link"
148 (textile-re-concat textile-alignments) "*"
149 "/?\\w[^ \n\t]*?\\(?: *(.*?)\\|\\w\\)"
152 (defun textile-acronym-matcher ()
153 "Return the matcher regexp for an acronym"
157 (defvar textile-font-lock-keywords
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)
167 `(,(textile-block-matcher "bq") 1 'textile-blockquote-face t t)
169 `(,(textile-block-matcher "fn[0-9]+") 1 'textile-footnote-face t t)
171 '("\\w\\([[0-9]+]\\)" 1 'textile-footnotemark-face prepend t)
173 `(,(textile-acronym-matcher) 0 'textile-acronym-face t t)
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)
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)
184 `(,(textile-inline-markup-matcher "\\?\\?") 1 'textile-citation-face prepend t)
186 `(,(textile-inline-markup-matcher "@") 1 'textile-code-face prepend t)
188 `(,(textile-inline-markup-matcher "-") 1 'textile-deleted-face prepend t)
190 `(,(textile-inline-markup-matcher "\\+") 1 'textile-inserted-face prepend t)
192 `(,(textile-inline-markup-matcher "\\^") 1 'textile-superscript-face prepend t)
194 `(,(textile-inline-markup-matcher "~") 1 'textile-subscript-face prepend t)
196 `(,(textile-inline-markup-matcher "%") 1 'textile-span-face prepend t)
199 `(,(textile-image-matcher) 0 'textile-image-face t t)
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)
207 `(,(textile-attribute-matcher "{" "}") 1 'textile-style-face t t)
209 `(,(textile-attribute-matcher "(" ")") 1 'textile-class-face t t)
211 `(,(textile-attribute-matcher "\\[" "\\]") 1 'textile-lang-face t t)
213 ;; alignments and indentation
214 `(,(textile-alignments-matcher) 1 'textile-alignments-face t t)
217 `(,(textile-table-matcher) 0 'textile-table-face t t)
220 `(,(textile-link-matcher) 0 'textile-link-face t t)
223 '("<pre>\\(.\\|\n\\)*?</pre>" 0 'textile-pre-face t t)
225 '("<code>\\(.\\|\n\\)*?</code>" 0 'textile-code-face t t))
226 "Keywords/Regexp for fontlocking of textile-mode")
229 ;; (defvar textile-imenu-generic-expression
232 ;; (defvar textile-outline-regexp
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))
246 (defgroup textile-faces nil
247 "Faces used by textile-mode for syntax highlighting"
250 (defface textile-h1-face
251 '((t (:height 2.0 :weight bold)))
252 "Face used to highlight h1 headers."
253 :group 'textile-faces)
255 (defface textile-h2-face
256 '((t (:height 1.75 :weight bold)))
257 "Face used to highlight h2 headers."
258 :group 'textile-faces)
260 (defface textile-h3-face
261 '((t (:height 1.6 :weight bold)))
262 "Face used to highlight h3 headers."
263 :group 'textile-faces)
265 (defface textile-h4-face
266 '((t (:height 1.35 :weight bold)))
267 "Face used to highlight h4 headers."
268 :group 'textile-faces)
270 (defface textile-h5-face
271 '((t (:height 1.2 :weight bold)))
272 "Face used to highlight h5 headers."
273 :group 'textile-faces)
275 (defface textile-h6-face
276 '((t (:height 1.0 :weight bold)))
277 "Face used to highlight h6 headers."
278 :group 'textile-faces)
280 (defface textile-blockquote-face
281 '((t (:foreground "ivory4")))
282 "Face used to highlight bq blocks."
283 :group 'textile-faces)
285 (defface textile-footnote-face
286 '((t (:foreground "orange red")))
287 "Face used to highlight footnote blocks."
288 :group 'textile-faces)
290 (defface textile-footnotemark-face
291 '((t (:foreground "orange red")))
292 "Face used to highlight footnote marks."
293 :group 'textile-faces)
295 (defface textile-style-face
296 '((t (:foreground "sandy brown")))
297 "Face used to highlight style parameters."
298 :group 'textile-faces)
300 (defface textile-class-face
301 '((t (:foreground "yellow green")))
302 "Face used to highlight class and id parameters."
303 :group 'textile-faces)
305 (defface textile-lang-face
306 '((t (:foreground "sky blue")))
307 "Face used to highlight lang parameters."
308 :group 'textile-faces)
310 (defface textile-emph-face
311 '((t (:slant italic)))
312 "Face used to highlight emphasized words."
313 :group 'textile-faces)
315 (defface textile-strong-face
316 '((t (:weight bold)))
317 "Face used to highlight strong words."
318 :group 'textile-faces)
320 (defface textile-code-face
321 '((t (:foreground "ivory3")))
322 "Face used to highlight inline code."
323 :group 'textile-faces)
325 (defface textile-citation-face
326 '((t (:slant italic)))
327 "Face used to highlight citations."
328 :group 'textile-faces)
330 (defface textile-deleted-face
331 '((t (:strike-through t)))
332 "Face used to highlight deleted words."
333 :group 'textile-faces)
335 (defface textile-inserted-face
336 '((t (:underline t)))
337 "Face used to highlight inserted words."
338 :group 'textile-faces)
340 (defface textile-superscript-face
342 "Face used to highlight superscript words."
343 :group 'textile-faces)
345 (defface textile-subscript-face
347 "Face used to highlight subscript words."
348 :group 'textile-faces)
350 (defface textile-span-face
351 '((t (:foreground "pink")))
352 "Face used to highlight span words."
353 :group 'textile-faces)
355 (defface textile-alignments-face
356 '((t (:foreground "cyan")))
357 "Face used to highlight alignments."
358 :group 'textile-faces)
360 (defface textile-ol-bullet-face
361 '((t (:foreground "red")))
362 "Face used to highlight ordered lists bullets."
363 :group 'textile-faces)
365 (defface textile-ul-bullet-face
366 '((t (:foreground "blue")))
367 "Face used to highlight unordered list bullets."
368 :group 'textile-faces)
370 (defface textile-pre-face
371 '((t (:foreground "green")))
372 "Face used to highlight <pre> blocks."
373 :group 'textile-faces)
375 (defface textile-code-face
376 '((t (:foreground "yellow")))
377 "Face used to highlight <code> blocks."
378 :group 'textile-faces)
380 (defface textile-table-face
381 '((t (:foreground "red")))
382 "Face used to highlight tables."
383 :group 'textile-faces)
385 (defface textile-link-face
386 '((t (:foreground "blue")))
387 "Face used to highlight links."
388 :group 'textile-faces)
390 (defface textile-image-face
391 '((t (:foreground "pink")))
392 "Face used to highlight image links."
393 :group 'textile-faces)
395 (defface textile-acronym-face
396 '((t (:foreground "cyan")))
397 "Face used to highlight acronyms links."
398 :group 'textile-faces)
401 (provide 'textile-mode)
402 ;;; textile-mode.el ends here