Hack on WikiName handling and make TAB work for Wiki links.
[muse-el.git] / lisp / muse-wiki.el
blobcee1788e44cf2a16006edab0a00f4bf2f29892d7
1 ;;; muse-wiki.el --- wiki features for muse
3 ;; Copyright (C) 2005 Free Software Foundation, Inc.
5 ;; Author: Yann Hodique <Yann.Hodique@lifl.fr>
6 ;; Keywords:
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.
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 the
20 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 ;; Boston, MA 02110-1301, USA.
23 ;;; Commentary:
25 ;;; Code:
27 (require 'muse-regexps)
28 (require 'muse-mode)
30 (defgroup muse-wiki nil
31 "Options controlling the behavior of Emacs Muse Wiki features."
32 :group 'muse-mode)
34 (defcustom muse-wiki-hide-nop-tag t
35 "If non-nil, hide <nop> tags when coloring a Muse buffer."
36 :type 'boolean
37 :group 'muse-wiki)
39 (defcustom muse-wiki-wikiword-regexp
40 (concat "\\<\\(\\(?:[" muse-regexp-upper
41 "][" muse-regexp-lower "]+\\)\\(?:["
42 muse-regexp-upper "][" muse-regexp-lower "]+\\)+\\)\\>")
43 "Regexp used to match WikiWords"
44 :type 'regexp
45 :group 'muse-wiki)
47 (defcustom muse-wiki-interwiki-alist
48 '(("EmacsWiki" . "http://www.emacswiki.org/cgi-bin/wiki/"))
49 "A table of WikiNames that refer to external entities.
50 The format of this table is an alist, or series of cons cells.
51 Each cons cell must be of the form:
53 (WIKINAME . STRING-OR-FUNCTION)
55 The second part of the cons cell may either be a STRING, which in most
56 cases should be a URL, or a FUNCTION. If a function, it will be
57 called with one argument: the tag applied to the Interwiki name, or
58 nil if no tag was used. If the cdr was a STRING and a tag is used,
59 the tag is simply appended.
61 Here are some examples:
63 (\"JohnWiki\" . \"http://alice.dynodns.net/wiki?\")
65 Referring to [[JohnWiki::EmacsModules]] then really means:
67 http://alice.dynodns.net/wiki?EmacsModules
69 If a function is used for the replacement text, you can get creative
70 depending on what the tag is. Tags may contain any alphabetic
71 character, any number, % or _. If you need other special characters,
72 use % to specify the hex code, as in %2E. All browsers should support
73 this."
74 :type '(repeat (cons (string :tag "WikiName")
75 (choice (string :tag "URL") function)))
76 :group 'muse-wiki)
78 (defvar muse-wiki-interwiki-regexp
79 (concat "\\<\\(" (mapconcat 'car muse-wiki-interwiki-alist "\\|")
80 "\\)\\(?:\\(?:#\\|::\\)\\(\\sw+\\)\\)?\\>"))
82 (defun muse-wiki-expand-interwiki (url)
83 (save-match-data
84 (setq url (or (muse-wiki-handle-interwiki url)
85 url))
86 (muse-publish-read-only url)))
88 (defun muse-wiki-handle-interwiki (url)
89 "If URL is an interwiki link, resolve it and return the result.
90 Match 1 is set to the original URL.
91 Match 2 is set to the description."
92 (when (string-match muse-wiki-interwiki-regexp url)
93 (let ((subst (cdr (assoc (match-string 1 url)
94 muse-wiki-interwiki-alist)))
95 (word (match-string 2 url)))
96 (if (functionp subst)
97 (funcall subst word)
98 (concat subst word)))))
100 (defun muse-wiki-handle-wikiword (link)
101 "If URL is a WikiWord, return it.
102 Match 1 is set to the WikiWord."
103 (and (string-match muse-wiki-wikiword-regexp link)
104 (match-string 1 link)))
106 ;; Coloring setup
108 (eval-after-load "muse-colors"
109 '(progn
110 (defun muse-wiki-colors-wikiword ()
111 ;; remove flyspell overlays
112 (when (fboundp 'flyspell-unhighlight-at)
113 (let ((cur (match-beginning 0)))
114 (while (> (match-end 0) cur)
115 (flyspell-unhighlight-at cur)
116 (setq cur (1+ cur)))))
117 (let ((link (match-string-no-properties 1))
118 (face (muse-link-face (match-string 1))))
119 (when face
120 (add-text-properties (match-beginning 1) (match-end 0)
121 (muse-link-properties
122 (match-string-no-properties 1) face)))))
124 (defun muse-wiki-colors-nop-tag (beg end)
125 (when (and muse-wiki-hide-nop-tag
126 (<= (- end beg) 5))
127 (add-text-properties beg end
128 '(invisible muse intangible t))))
130 (add-to-list 'muse-colors-tags
131 '("nop" nil nil muse-wiki-colors-nop-tag)
134 (add-to-list 'muse-colors-markup
135 '(muse-wiki-interwiki-regexp t muse-wiki-colors-wikiword)
137 (add-to-list 'muse-colors-markup
138 '(muse-wiki-wikiword-regexp t muse-wiki-colors-wikiword)
141 (muse-configure-highlighting 'muse-colors-markup muse-colors-markup)))
143 ;; Publishing setup
145 (eval-after-load "muse-publish"
146 '(progn
147 (add-to-list 'muse-publish-markup-regexps
148 '(3100 muse-wiki-interwiki-regexp 0 url)
150 (add-to-list 'muse-publish-markup-regexps
151 '(3200 muse-wiki-wikiword-regexp 0 url)
154 (add-to-list 'muse-publish-url-transforms
155 'muse-wiki-expand-interwiki)))
157 ;; Insinuate link handling
159 (add-to-list 'muse-implicit-link-functions
160 'muse-wiki-handle-interwiki t)
161 (add-to-list 'muse-implicit-link-functions
162 'muse-wiki-handle-wikiword t)
164 (add-to-list 'muse-explicit-link-functions
165 'muse-wiki-handle-interwiki)
167 (provide 'muse-wiki)
168 ;;; muse-wiki.el ends here