Jump to bad and good links on TAB; mode-choosing fix.
[muse-el.git] / experimental / muse-wiki-old.el
blob4849f4374e0c71290095737770954124a82c58f6
1 ;;; muse-blosxom.el --- Publish a document tree for serving by (py)Blosxom
3 ;; Copyright (C) 2004, 2005 Free Software Foundation, Inc.
5 ;; Date: Wed, 13 June 2005
6 ;; Author: Michael Olson (mwolson AT gnu DOT org)
7 ;; Maintainer: Michael Olson (mwolson AT gnu DOT org)
9 ;; This file is not part of GNU Emacs.
11 ;; This is free software; you can redistribute it and/or modify it under
12 ;; the terms of the GNU General Public License as published by the Free
13 ;; Software Foundation; either version 2, or (at your option) any later
14 ;; version.
16 ;; This is distributed in the hope that it will be useful, but WITHOUT
17 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 ;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19 ;; for more details.
21 ;; You should have received a copy of the GNU General Public License
22 ;; along with GNU Emacs; see the file COPYING. If not, write to the
23 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
24 ;; Boston, MA 02110-1301, USA.
26 ;;; Commentary:
28 ;; This file is in experimental status.
30 ;; It was a collection of routines that were removed from Muse because
31 ;; they didn't fit neatly into its paradigm. Eventually it is hoped
32 ;; that this will provide bare WikiName and interwiki support.
34 ;; Yann Hodique's implementation of WikiName highlighting will
35 ;; probably be merged into this file, or something to that effect.
37 ;;; Contributors:
39 ;;; Code:
41 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
43 ;; Muse Wiki Publishing and Highlighting
45 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
47 ;; This was a removed rule from `muse-publish-markup-regexps'.
49 ;; ["''''" 0 ""]
51 (defcustom muse-interwiki-names
52 '(("GnuEmacs" . "http://www.gnu.org/software/emacs/emacs.html")
53 ("TheEmacsWiki" .
54 (lambda (tag)
55 (concat "http://www.emacswiki.org/cgi-bin/wiki.pl?"
56 (or tag "SiteMap"))))
57 ("MeatballWiki" .
58 (lambda (tag)
59 (concat "http://www.usemod.com/cgi-bin/mb.pl?"
60 (or tag "MeatballWiki")))))
61 "A table of WikiNames that refer to external entities.
62 The format of this table is an alist, or series of cons cells.
63 Each cons cell must be of the form:
65 (WIKINAME . STRING-OR-FUNCTION)
67 The second part of the cons cell may either be a STRING, which in most
68 cases should be a URL, or a FUNCTION. If a function, it will be
69 called with one argument: the tag applied to the Interwiki name, or
70 nil if no tag was used. If the cdr was a STRING and a tag is used,
71 the tag is simply appended.
73 Here are some examples:
75 (\"JohnWiki\" . \"http://alice.dynodns.net/wiki?\")
77 Referring to [[JohnWiki#EmacsModules]] then really means:
79 http://alice.dynodns.net/wiki?EmacsModules
81 If a function is used for the replacement text, you can get creative
82 depending on what the tag is. Tags may contain any alphabetic
83 character, any number, % or _. If you need other special characters,
84 use % to specify the hex code, as in %2E. All browsers should support
85 this."
86 :type '(repeat (cons (string :tag "WikiName")
87 (choice (string :tag "URL") function)))
88 :group 'muse)
90 (defcustom muse-publish-small-title-words
91 '("the" "and" "at" "on" "of" "for" "in" "an" "a")
92 "Strings that should be downcased in a page title."
93 :type '(repeat string)
94 :group 'muse-publish)
96 (defun muse-publish-pretty-title (title)
97 "Return a pretty version of the given TITLE."
98 (save-match-data
99 (let ((case-fold-search nil))
100 (while (string-match "\\([A-Za-z]\\)\\([A-Z0-9]\\)" title)
101 (setq title (replace-match "\\1 \\2" t nil title)))
102 (let* ((words (split-string title))
103 (w (cdr words)))
104 (while w
105 (if (member (downcase (car w))
106 muse-publish-small-title-words)
107 (setcar w (downcase (car w))))
108 (setq w (cdr w)))
109 (mapconcat 'identity words " ")))))
111 (defun muse-publish-nop-tag (beg end)
112 (when (looking-at "\\<[A-Z][a-z]+\\([A-Z][a-z]+\\)+")
113 (goto-char (match-end 0))
114 (muse-publish-mark-read-only beg (point))))
116 ;; regenerate the index if any pages were published
117 (with-current-buffer (muse-generate-index t t)
118 (muse-replace-markup muse-publish-index-page)
119 (let ((backup-inhibited t))
120 (write-file (muse-published-file muse-publish-index-page)))
121 (kill-buffer (current-buffer))
122 (message "All pages in %s have been published." (car project)))
125 (defun muse-count-chars (string char)
126 (let ((i 0)
127 (l (length string))
128 (count 0))
129 (while (< i l)
130 (if (eq char (aref string i))
131 (setq count (1+ count)))
132 (setq i (1+ i)))
133 count))
135 (defun muse-set-sym-and-url-regexp (sym value)
136 (setq muse-url-or-name-regexp
137 (concat "\\("
138 (if (eq sym 'muse-name-regexp)
139 value
140 muse-name-regexp) "\\|"
141 (if (eq sym 'muse-name-regexp)
142 (if (boundp 'muse-url-regexp)
143 muse-url-regexp
145 value) "\\)")
146 muse-url-or-name-regexp-group-count
147 (- (muse-count-chars
148 muse-url-or-name-regexp ?\() 2))
149 (set sym value))
151 (defcustom muse-name-regexp
152 (concat "\\(" muse-extended-link-regexp "\\|"
153 "\\<[A-Z][a-z]+\\([A-Z][a-z]+\\)+\\(#\\S-+[A-Za-z0-9]\\)?" "\\)")
154 "Regexp used to match WikiNames."
155 :type 'regexp
156 :set 'muse-set-sym-and-url-regexp
157 :group 'muse)
159 (defvar muse-url-or-name-regexp nil
160 "Matches either a Wiki link or a URL. This variable is auto-generated.")
162 (defvar muse-url-or-name-regexp-group-count nil
163 "Matches either a Wiki link or a URL. This variable is auto-generated.")
165 ;; Utility functions to extract parts of a Wiki name
167 (defvar muse-serving-p nil
168 "Non-nil when Muse is serving a page directly.")
170 (defsubst muse-transform-name (name)
171 "Transform NAME as per `muse-publishing-transforms', returning NAME"
172 (save-match-data
173 (mapc (function
174 (lambda (elt)
175 (let ((reg (car elt))
176 (rep (cdr elt)))
177 (when (string-match reg name)
178 (setq name (replace-match rep t nil name))))))
179 muse-publishing-transforms)
180 name))
182 (defsubst muse-published-name (name &optional current)
183 "Return the externally visible NAME for a wiki page, possibly transformed
184 via `muse-publishing-transforms'. If CURRENT is provided, convert any
185 path to be relative to it"
186 (muse-transform-name
187 (progn
188 (when current
189 (setq name (file-relative-name name
190 (file-name-directory
191 (muse-transform-name current)))))
192 (concat (if muse-serving-p
193 (unless (string-match "\\?" name) "wiki?")
194 muse-publishing-file-prefix)
195 name
196 (unless muse-serving-p
197 muse-publishing-file-suffix)))))
199 (defsubst muse-published-file (&optional file)
200 "Return the filename of the published file. Since this is based on the
201 published-name, it will be filtered through
202 `muse-publishing-transforms'"
203 (expand-file-name (muse-published-name (muse-page-name
204 file))
205 muse-publishing-directory))
207 (defcustom muse-publishing-transforms nil
208 "A list of cons cells mapping regexps to replacements, which is
209 applied when generating the published name from the wiki file
210 name. The replacements run in order so you can chain them
211 together.
213 An example is how I publish the Muse documentation. The Muse
214 homepage is in a file called EmacsWiki. With the following
215 settings I can publish directly to my webserver via tramp (the
216 first rule catches 'WikiMarkup' for instance):
218 (setq muse-publishing-directory \"/webserver:/var/www/\")
219 (setq muse-publishing-transforms
220 '((\".*Wiki.*\" . \"emacs/wiki/\\&\")
221 (\"EmacsWiki\\|WelcomePage\" . \"index\")))
223 Then when trying to publish a page EmacsWiki:
225 (muse-published-file \"EmacsWiki\")
227 You get:
229 \"/webserver:/var/www/emacs/wiki/index.html\""
230 :type '(repeat
231 (cons
232 (regexp :tag "String to match")
233 (string :tag "Replacement string")))
234 :group 'muse-publish)
236 (defsubst muse-wiki-url-p (name)
237 "Return non-nil if NAME is a URL."
238 (save-match-data
239 (and name
240 (string-match muse-url-regexp name))))
242 (defun muse-wiki-visible-name (wiki-name)
243 "Return the visible part of a Wiki link.
244 This only really means something if [[extended][links]] are involved."
245 (save-match-data
246 (let ((name wiki-name))
247 (if (string-match muse-extended-link-regexp name)
248 (if (match-string 2 name)
249 (setq name (match-string 3 name))
250 (setq name (match-string 1 name))))
251 (if (and (not (muse-wiki-url-p name))
252 (string-match "#" name))
253 (if (= 0 (match-beginning 0))
254 (setq name (muse-page-name))
255 (let ((base (substring name 0 (match-beginning 0))))
256 (if (assoc base muse-interwiki-names)
257 (setq name (concat (substring name 0 (match-beginning 0))
258 ":" (substring name (match-end 0))))
259 (setq name base)))))
260 name)))
262 (defun muse-wiki-tag (wiki-name)
263 (save-match-data
264 (if (string-match "#" wiki-name)
265 (substring wiki-name (match-end 0)))))
267 (defun muse-wiki-link-target (wiki-name)
268 "Return the target of a Wiki link. This might include anchor tags."
269 (save-match-data
270 (let ((name wiki-name) lookup)
271 (if (string-match "^\\[\\[\\([^]]+\\)\\]" name)
272 (setq name (match-string 1 name)))
273 (if (and muse-interwiki-names
274 (string-match "\\`\\([^#]+\\)\\(#\\(.+\\)\\)?\\'" name)
275 (setq lookup (assoc (match-string 1 name)
276 muse-interwiki-names)))
277 (let ((tag (match-string 3 name))
278 (target (cdr lookup)))
279 (if (stringp target)
280 (setq name (concat target tag))
281 (setq name (funcall target tag))))
282 (if (and (> (length name) 0)
283 (eq (aref name 0) ?#))
284 (setq name (concat (muse-page-name) name))))
285 name)))
287 (defun muse-wiki-base (wiki-name)
288 "Find the WikiName or URL mentioned by a Wiki link.
289 This means without tags, in the case of a WikiName."
290 (save-match-data
291 (let ((file (muse-wiki-link-target wiki-name)))
292 (if (muse-wiki-url-p file)
293 file
294 (if (string-match "#" file)
295 (substring file 0 (match-beginning 0))
296 file)))))