Attachment 'moinmoin-mode.el'
Download 1 ;;; Use raw text to fetch this code, see EmacsForMoinMoin for tutorial and discussion.
2
3 ;;; Download link: http://moinmo.in/EmacsForMoinMoin/MoinMoinMode?action=raw
4
5 ;;; moinmoin-mode.el --- a major mode to edit MoinMoin wiki pages
6
7 ;; Written by ASK, distributed under GPL
8
9 ;; Filename: moinmoin-mode.el
10 ;; Keywords: moinmoin, wiki
11 ;; Description: a major mode to edit MoinMoin wiki pages
12 ;; Compatibility: GNU Emacs 22.0.50.1 (probably others)
13 ;; Last modified: 2006-04-15
14
15 ;; This file is NOT part of GNU Emacs.
16
17 ;(require 'screen-lines) ; uses screen-lines.el by Yuji Minejima, tested with 0.55
18
19
20 ;;; Definition of font faces
21 (defgroup moinmoin nil
22 "Major mode for MoinMoin wiki pages"
23 :prefix "moinmoin-")
24
25 (defface moinmoin-h5 '((t (:foreground "tan3" :slant italic)))
26 "Face name to use for 5-level headings in moinmoin"
27 :group 'moinmoin)
28 (defface moinmoin-h4 '((t (:inherit moinmoin-h5 :slant normal :foreground "tan4")))
29 "Face name to use for 4-level headings in moinmoin"
30 :group 'moinmoin)
31 (defface moinmoin-h3 '((t (:inherit moinmoin-h4 :weight bold)))
32 "Face name to use for 3-level headings in moinmoin"
33 :group 'moinmoin)
34 (defface moinmoin-h2 '((t (:inherit moinmoin-h3 :height 1.2)))
35 "Face name to use for 3-level headings in moinmoin"
36 :group 'moinmoin)
37 (defface moinmoin-h1 '((t (:inherit moinmoin-h2 :height 1.4)))
38 "Face name to use for 3-level headings in moinmoin"
39 :group 'moinmoin)
40
41 (defface moinmoin-smiley '((t (:foreground "green4" :weight bold)))
42 "Face name to use smileys in moinmoin"
43 :group 'moinmoin)
44
45 (defface moinmoin-table-separator '((t (:foreground "salmon" :weight bold)))
46 "Face name to use for separation of columns in tables of moinmoin"
47 :group 'moinmoin)
48 (defface moinmoin-table-pi '((t (:foreground "plum3")))
49 "Face name to use for processing instructions in tables of moinmoin"
50 :group 'moinmoin)
51
52 (defface moinmoin-anchor '((t (:foreground "tan3" :height 0.8)))
53 "Face name to use for anchors (targets) in moinmoin"
54 :group 'moinmoin)
55 (defface moinmoin-anchor-ref-id '((t (:foreground "blue2" :height 0.8 :underline t)))
56 "Face name to use for id in anchor reference in moinmoin"
57 :group 'moinmoin)
58 (defface moinmoin-anchor-ref-title '((t (:foreground "blue4" :underline t)))
59 "Face name to use for title in anchors reference in moinmoin"
60 :group 'moinmoin)
61
62 (defface moinmoin-macro-name '((t (:foreground "plum3")))
63 "Face name to use for names of macros in moinmoin"
64 :group 'moinmoin)
65 (defface moinmoin-macro-parameters '((t (:foreground "plum4")))
66 "Face name to use for parameters of macros in moinmoin"
67 :group 'moinmoin)
68
69 (defface moinmoin-item '((t (:foreground "brown" :weight bold)))
70 "Face name to use for items in lists in moinmoin"
71 :group 'moinmoin)
72 (defface moinmoin-item-2 '((t (:foreground "brown")))
73 "Face name to use for second-level items in moinmoin"
74 :group 'moinmoin)
75 (defface moinmoin-blockquote-indent '((t (:background "aquamarine1")))
76 "Face name to use for blockquote indentation in moinmoin"
77 :group 'moinmoin)
78 (defface moinmoin-blockquote-text '((t (:foreground "aquamarine4")))
79 "Face name to use for blockquote text in moinmoin"
80 :group 'moinmoin)
81
82 (defface moinmoin-code '((t (:foreground "purple4")))
83 "Face name to use for code inside braces in moinmoin"
84 :group 'moinmoin)
85 (defface moinmoin-code-braces '((t (:foreground "plum3")))
86 "Face name to use for baces which delimit code inside braces in moinmoin"
87 :group 'moinmoin)
88
89 (defface moinmoin-pi '((t (:foreground "plum3" :weight bold)))
90 "Face name to use for processing instructions in moinmoin"
91 :group 'moinmoin)
92 (defface moinmoin-comment '((t (:foreground "maroon3")))
93 "Face name to use for comments in moinmoin"
94 :group 'moinmoin)
95 (defface moinmoin-rule '((t (:foreground "tomato2" :weight bold)))
96 "Face name to use for rules in moinmoin"
97 :group 'moinmoin)
98 (defface moinmoin-ss '((t (:foreground "grey" ))) ;; try also :height 0.1
99 "Face name to use for syntactic sugar in moinmoin"
100 :group 'moinmoin)
101 (defface moinmoin-tt '((t (:foreground "cyan4")))
102 "Face name to use for typewriter text in moinmoin"
103 :group 'moinmoin)
104 (defface moinmoin-entity '((t (:foreground "grey")))
105 "Face name to use for HTML entities in moinmoin"
106 :group 'moinmoin)
107 (defface moinmoin-email '((t (:foreground "blue2")))
108 "Face name to use for emails in moinmoin"
109 :group 'moinmoin)
110 (defface moinmoin-url '((t (:foreground "blue2" :height 0.8)))
111 "Face name to use for URLs in moinmoin"
112 :group 'moinmoin)
113 (defface moinmoin-url-title '((t (:foreground "blue4" :underline t)))
114 "Face name to use for title of URL in moinmoin"
115 :group 'moinmoin)
116 (defface moinmoin-wiki-link '((t (:foreground "blue4" :weight bold)))
117 "Face name to use for CamelCase links in moinmoin"
118 :group 'moinmoin)
119 (defface moinmoin-inter-wiki-link '((t (:foreground "blue3" :weight bold)))
120 "Face name to use for inter wiki links in moinmoin"
121 :group 'moinmoin)
122 (defface moinmoin-bold '((t (:weight bold)))
123 "Face name to use for bold text in moinmoin"
124 :group 'moinmoin)
125 (defface moinmoin-italic '((t (:slant italic)))
126 "Face name to use for italic text in moinmoin"
127 :group 'moinmoin)
128 (defface moinmoin-underline '((t (:underline t)))
129 "Face name to use for underlined text in moinmoin"
130 :group 'moinmoin)
131 (defface moinmoin-stroke '((t (:strike-through t)))
132 "Face name to use for stroked text in moinmoin"
133 :group 'moinmoin)
134 (defface moinmoin-subscript '((t (:height 0.8)))
135 "Face name to use for subscripts in moinmoin"
136 :group 'moinmoin)
137 (defface moinmoin-superscript '((t (:height 0.8)))
138 "Face name to use for superscripts in moinmoin"
139 :group 'moinmoin)
140
141
142 ;;; Font lock setup
143 (defconst moinmoin-url-prefix
144 "\\(?:http\\|https\\|ftp\\|nntp\\|news\\|mailto\\|telnet\\|wiki\\|file\\|irc\\|attachment\\|inline\\|drawing\\)"
145 "Bracketed regexp matching URL prefixes in moinmoin")
146 (defconst moinmoin-url-punctuation
147 "]\"'}|:,.)?!" ; start with ]
148 "Punctuation in URLs of moinmoin")
149 (defconst moinmoin-pi-re
150 "^#\\(?:format\\|refresh\\|redirect\\|deprecated\\|pragma\\|form\\|acl\\|language\\).*$"
151 "Regexp for processing instructions in moinmoin")
152 (defconst moinmoin-smiley-re
153 "\\(?:<:(\\|X-(\\|:)\\|:-))\\|:(\\|/!\\\\\\|{X}\\|{OK}\\|B-)\\|{2}\\|>:>\\|;-)\\|<!>\\|:o\\||-)\\|;)\\||)\\|(!)\\|:-(\\|:-)\\|{o}\\|:D\\|(./)\\|B)\\|{*}\\|:\\\|:-?\\|{i}\\|{3}\\|{1}\\|:)\\)"
154 "Regexp for smileys in moinmoin")
155
156 (defun moinmoin-formatted-code-matcher (bound)
157 "Search for formatted code
158 This is supposed to be bug-to-bug compatible with moinmoin-1.5.2"
159 (catch 'match
160 (while (< (point) bound)
161 (unless (search-forward-regexp "{{{" bound t)
162 (throw 'match nil))
163 (let ((start-brace-begin (match-beginning 0))
164 (start-brace-end (match-end 0))
165 pi-begin pi-end
166 code-begin code-end
167 end-brace-begin end-brace-end)
168 (unless (get-text-property start-brace-begin 'moinmoin-verbatim)
169 (goto-char start-brace-end)
170 (if (looking-at "#!.*\n")
171 (setq pi-begin (match-beginning 0)
172 pi-end (match-end 0)
173 code-begin (match-end 0))
174 (setq code-begin start-brace-end))
175 (goto-char code-begin)
176 (let ((not-first-line))
177 (while (looking-at
178 "\\(?:##.*\\|`.*?`\\|{{{.*?}}}\\|.\\)*?\\(?:\\(}}}\\)\\|\n\\)")
179 (goto-char (match-end 0))
180 (when (and (match-beginning 1) ; non-paired `}}}'
181 not-first-line)
182 (setq code-end (match-beginning 1)
183 end-brace-begin (match-beginning 1)
184 end-brace-end (match-end 1))
185 (set-match-data (list start-brace-begin end-brace-end
186 start-brace-begin start-brace-end
187 pi-begin pi-end
188 code-begin code-end
189 end-brace-begin end-brace-end))
190 (throw 'match t))
191 (setq not-first-line t)))
192 (throw 'match nil))))))
193
194
195 (defun moinmoin-bracketed-url-matcher (bound)
196 "Search for bracketed URLs"
197 (catch 'match
198 (while (< (point) bound)
199 (unless (search-forward-regexp
200 (concat "\\(\\[\\)"
201 "\\(" moinmoin-url-prefix "?:.*?\\) +"
202 "\\(.*?\\)?"
203 "\\(\\]\\)") bound t)
204 (throw 'match nil))
205 (unless (get-text-property (match-beginning 0) 'moinmoin-verbatim)
206 (throw 'match t)))))
207
208 (defun moinmoin-setup-font-lock ()
209 ; (setq font-lock-beginning-of-syntax-function '(lambda () (goto-char 1)))
210 (setq font-lock-multiline t)
211 (make-local-variable 'font-lock-extra-managed-props)
212 (add-to-list 'font-lock-extra-managed-props 'moinmoin-verbatim) ; Not Comment Start
213 (add-to-list 'font-lock-extra-managed-props 'display)
214 (font-lock-add-keywords nil `(
215 ("\\(?:^\\|[^|]\\)\\(\\(?:||\\)+\\)\\(<.*?>\\)?"
216 (1 'moinmoin-table-separator)
217 (2 'moinmoin-table-pi t t))
218 ("'''\\(.*?\\)'''" (1 'moinmoin-bold prepend))
219 ("\\(?:[^']\\|^\\)''\\([^'].*?[^']\\)''[^']" (1 'moinmoin-italic prepend))
220 ("\\(__\\)\\(.*?\\)\\(__\\)"
221 (1 'moinmoin-ss t) (2 'moinmoin-underline prepend) (3 'moinmoin-ss t))
222 ("\\(--(\\)\\(.*?\\)\\()--\\)"
223 (1 'moinmoin-ss t) (2 'moinmoin-stroke prepend) (3 'moinmoin-ss t))
224 ("\\(,,\\)\\(.*?\\)\\(,,\\)"
225 (1 'moinmoin-ss t)
226 (2 (list 'face 'moinmoin-subscript 'display '(raise -0.3)) prepend)
227 (3 'moinmoin-ss t))
228 ("\\(\\^\\)\\(.*?\\)\\(\\^\\)"
229 (1 'moinmoin-ss t)
230 (2 (list 'face 'moinmoin-superscript 'display '(raise 0.3)) prepend)
231 (3 'moinmoin-ss t))
232 ("''+" (0 'moinmoin-ss t))
233 ("^ +\\(?:\\*\\|.*?::\\|\\(?:[0-9]+\\|[aAiI]\\)\\.\\) "
234 (0 'moinmoin-item-2))
235 ("^ \\(?:\\*\\|.*?::\\|\\(?:[0-9]+\\|[aAiI]\\)\\.\\) "
236 (0 'moinmoin-item))
237 ("^\\( +\\)\\(.*\\)"
238 (1 'moinmoin-blockquote-indent)
239 (2 'moinmoin-blockquote-text))
240 ("&[A-Za-z0-9]*;" (0 'moinmoin-entity prepend))
241 (,(concat "\\(?:^\\| \\)\\(" moinmoin-smiley-re "\\)[[:space:]]")
242 (1 'moinmoin-smiley t))
243 ("\\(?:^\\|[^A-Za-z!]\\)\\(\\(?:\\.\\./\\)?/?[A-Z][a-z]+[A-Z][a-z][A-Za-z]*\\(?:/[A-Z][a-z]+[A-Z][a-z][A-Za-z]*\\)?\\)"
244 (1 'moinmoin-wiki-link t))
245 (,(concat "[A-Z][A-Za-z]+:"
246 "[^[:space:]'\":<|]"
247 "\\(?:[^" moinmoin-url-punctuation "[:space:]]\\|"
248 "[" moinmoin-url-punctuation "]"
249 "[^" moinmoin-url-punctuation "[:space:]]\\)+")
250 (0 'moinmoin-inter-wiki-link t))
251 ("\\(\\[\"\\)\\(?:\\(.*?:.*\\)\\|\\(.*?\\)\\)\\(\"\\]\\)"
252 (1 'moinmoin-ss t)
253 (2 (list 'face 'moinmoin-inter-wiki-link 'moinmoin-verbatim t) t t)
254 (3 (list 'face 'moinmoin-wiki-link 'moinmoin-verbatim t) t t)
255 (4 'moinmoin-ss t))
256 ;;ur'%(url_guard)s(%(url)s)\:([^\s\<%(punct)s]|([%(punct)s][^\s\<%(punct)s]))+'
257 (,(concat "\\<" moinmoin-url-prefix ":"
258 "\\(?:[^" moinmoin-url-punctuation "<[:space:]]\\|"
259 "[" moinmoin-url-punctuation "]"
260 "[^" moinmoin-url-punctuation "<[:space:]]\\)+")
261 (0 'moinmoin-url t))
262 ("[A-Za-z0-9_+-]+@[A-Za-z0-9_-]+\\(?:\\.[A-Za-z0-9_-]+\\)+"
263 (0 'moinmoin-email t))
264 ("-\\{4,\\}" (0 'moinmoin-rule t))
265 ;; macros
266 ("\\(\\[\\[\\)\\([A-Za-z0-9]+\\)\\(?:\\((\\)\\(.*?\\)\\()\\)\\)?\\(\\]\\]\\)"
267 (1 'moinmoin-ss t)
268 (2 (list 'face 'moinmoin-macro-name 'moinmoin-verbatim t) t)
269 (3 'moinmoin-ss t t)
270 (4 (list 'face 'moinmoin-macro-parameters 'moinmoin-verbatim t) t t)
271 (5 'moinmoin-ss t t)
272 (6 'moinmoin-ss t))
273 ("\\(\\[\\[Anchor(\\)\\(.*?\\)\\()\\]\\]\\)"
274 (1 'moinmoin-ss t)
275 (2 (list 'face 'moinmoin-anchor 'moinmoin-verbatim t) t)
276 (3 'moinmoin-ss t))
277 ("\\(\\[#\\)\\(.*?\\) +\\(.*?\\)?\\(\\]\\)"
278 (1 'moinmoin-ss t)
279 (2 (list 'face 'moinmoin-anchor-ref-id 'moinmoin-verbatim t) t)
280 (3 (list 'face 'moinmoin-anchor-ref-title 'moinmoin-verbatim t) t t)
281 (4 (list 'face 'moinmoin-ss 'moinmoin-verbatim t) t))
282 ;; typewriter (tt) overrides the above
283 ("\\({{{\\)\\(.*?\\)\\(}}}\\)"
284 (1 (list 'face 'moinmoin-ss 'moinmoin-verbatim t) keep)
285 (2 (list 'face 'moinmoin-tt 'moinmoin-verbatim t) t)
286 (3 (list 'face 'moinmoin-ss 'moinmoin-verbatim t) keep))
287 ("\\(`\\)\\(.*?\\)\\(`\\)"
288 (1 'moinmoin-ss keep) ; cannot match `{{{' thus no need for ncs
289 (2 (list 'face 'moinmoin-tt 'moinmoin-verbatim t) t)
290 (3 'moinmoin-ss keep))
291 ;; headers overrides tt and biu
292 ("^\\(= \\)\\(.*\\)\\( =\\)$"
293 (1 'moinmoin-ss t)
294 (2 (list 'face 'moinmoin-h1 'moinmoin-verbatim t) t)
295 (3 'moinmoin-ss t))
296 ("^\\(== \\)\\(.*\\)\\( ==\\)$"
297 (1 'moinmoin-ss t)
298 (2 (list 'face 'moinmoin-h2 'moinmoin-verbatim t) t)
299 (3 'moinmoin-ss t))
300 ("^\\(=== \\)\\(.*\\)\\( ===\\)$"
301 (1 'moinmoin-ss t)
302 (2 (list 'face 'moinmoin-h3 'moinmoin-verbatim t) t)
303 (3 'moinmoin-ss t))
304 ("^\\(==== \\)\\(.*\\)\\( ====\\)$"
305 (1 'moinmoin-ss t)
306 (2 (list 'face 'moinmoin-h4 'moinmoin-verbatim t) t)
307 (3 'moinmoin-ss t))
308 ("^\\(=====\\(=*\\) \\)\\(.*\\)\\( \\2=====\\)$" ; 5th and all others
309 (1 'moinmoin-ss t)
310 (3 (list 'face 'moinmoin-h5 'moinmoin-verbatim t) t)
311 (4 'moinmoin-ss t))
312 ;; comments and pi
313 ("^##.*$"
314 (0 (list 'face 'moinmoin-comment 'moinmoin-verbatim t) t))
315 (,moinmoin-pi-re
316 (0 (list 'face 'moinmoin-pi 'moinmoin-verbatim t) t))
317 (moinmoin-bracketed-url-matcher
318 (1 'moinmoin-ss t)
319 (2 (list 'face 'moinmoin-url 'moinmoin-verbatim t) t)
320 (3 (list 'face 'moinmoin-url-title 'moinmoin-verbatim t) t t)
321 (4 (list 'face 'moinmoin-ss 'moinmoin-verbatim t) t))
322 (moinmoin-formatted-code-matcher
323 (1 (list 'face 'moinmoin-code-braces 'moinmoin-verbatim t) t)
324 (2 (list 'face 'moinmoin-pi 'moinmoin-verbatim t) t t)
325 (3 (list 'face 'moinmoin-code 'moinmoin-verbatim t) t)
326 (4 (list 'face 'moinmoin-code-braces 'moinmoin-verbatim t) t))
327 ) 'set))
328
329
330 ;;; Automagic typing helpers
331 (defun moinmoin-insert-quote ()
332 "Convert double quote to HTML entity (“ or ”)"
333 (interactive)
334 (cond
335 ((or (get-text-property (point) 'moinmoin-verbatim)
336 (looking-back "\\[\\|= *\\|^\\(?:[^\"]*\"[^\"]*\"\\)*[^\"]*\"[^\"]*"))
337 (insert "\""))
338 ((or (looking-back "[[:space:]]") (eq (point) 1))
339 (insert "“"))
340 (t (insert "”"))))
341
342 (defun moinmoin-insert-dash ()
343 "Insert different types of dashes.
344 `----' and `-' stays unchanged
345 `--' is converted to `–'
346 `---' is converted to `—'
347 `)--' is not changed'
348 `<-' is converted to `←'"
349 (interactive)
350 (cond
351 ((get-text-property (point) 'moinmoin-verbatim)
352 (insert "-"))
353 ((looking-back "---\\|—")
354 (replace-match "----" t t))
355 ((looking-back "--\\|–")
356 (replace-match "—" t t))
357 ((looking-back ")-")
358 (replace-match ")--" t t))
359 ((looking-back "<")
360 (replace-match "←" t t))
361 ((looking-back "-")
362 (replace-match "–" t t))
363 (t (insert "-"))))
364
365 (defun moinmoin-insert-lparen ()
366 "–( to --("
367 (interactive)
368 (cond
369 ((get-text-property (point) 'moinmoin-verbatim)
370 (insert "("))
371 ((looking-back "–")
372 (replace-match "--(" t t))
373 (t (insert "("))))
374
375 (defun moinmoin-insert-greater-than ()
376 "-> to →"
377 (interactive)
378 (cond
379 ((get-text-property (point) 'moinmoin-verbatim)
380 (insert ">"))
381 ((looking-back "-")
382 (replace-match "→" t t))
383 (t (insert ">"))))
384
385 (defun moinmoin-insert-item ()
386 "Start new item or row
387 If current line starts with item prefix insert newline and the same
388 prefix in front of the rest of line.
389 If it is table then finish the line and add the new one"
390 (interactive)
391 (when (bolp) (backward-char))
392 (cond
393 ((looking-back "^\\( *||\\).*") ; in a table
394 (let ((prefix (match-string 1)))
395 (end-of-line)
396 (looking-back "[^|]\\(|*\\)")
397 (replace-match "||" t t nil 1)
398 (insert "\n" prefix)))
399 ((looking-back "^\\( +\\(?:\\* \\|\\(?:[0-9]+\\|[aAiI]\\)\\. \\|\\)\\).*")
400 (let ((prefix (match-string 1)))
401 (insert "\n")
402 (insert prefix)))))
403
404
405 ;;; Header manipulation helpers
406 (defun moinmoin-is-header ()
407 "Is point in a header line?
408 If yes the title is in \\1"
409 (save-excursion
410 (beginning-of-line)
411 (looking-at "=+ \\(.*\\) =+$")))
412
413 (defun moinmoin-increase-header-level ()
414 "Add `=' in the beginning and end of current line"
415 (save-excursion
416 (beginning-of-line) (insert "=")
417 (end-of-line) (insert "=")))
418
419 (defun moinmoin-decrease-header-level ()
420 "Decrease level of the header
421 Warns if point in a top-level header or not in a header"
422 (save-excursion
423 (beginning-of-line)
424 (if (looking-at "=\\(=+ .* =+\\)=$")
425 (replace-match "\\1" t)
426 (warn "cannot decrease level"))
427 ))
428
429 (defun moinmoin-change-header-level (increment)
430 "Increase or decrease level of header according to INCREMENT"
431 (interactive "r")
432 (if (eq increment 1)
433 (moinmoin-increase-header-level)
434 (moinmoin-decrease-header-level)))
435
436 (defun moinmoin-change-header-levels-in-region (increment start end)
437 "Increase or decrease level of all headers in the region according to INCREMENT"
438 (interactive "p\nr")
439 (save-excursion
440 (goto-char start)
441 (while (progn
442 (when (moinmoin-is-header)
443 (moinmoin-change-header-level increment))
444 (and (zerop (forward-line)) (< (point) end))))
445 ))
446
447 (defun moinmoin-insert-equal (increment)
448 "Do-what-I-mean with header level or insert `='.
449 With active region increase or decrease level of all headers in region.
450 On an empty line starts new header.
451 On a header line increase or decrease level.
452 Otherwise just insert `='"
453 (interactive "p")
454 (if mark-active
455 (progn
456 (moinmoin-change-header-levels-in-region
457 increment (region-beginning) (region-end))
458 (setq deactivate-mark nil))
459 (cond
460 ((looking-at "^$")
461 (insert "= =")
462 (backward-char 2))
463 ((moinmoin-is-header)
464 (moinmoin-change-header-level increment))
465 (t (insert "=")))))
466
467
468 ;;; Anchor insertion and navigation
469 (defun moinmoin-list-anchors ()
470 "List anchors in the current buffer"
471 (let ((lst))
472 (save-excursion
473 (goto-char 1)
474 (while (search-forward-regexp "\\[\\[Anchor(\\([^])\n]*\\))\\]\\]" nil t)
475 (setq lst (cons (match-string-no-properties 1) lst))))
476 lst))
477
478 (defvar moinmoin-anchor-history "Minibuffer history of anchors")
479 (defun moinmoin-completing-read-anchor (prompt &optional require-match)
480 "Read non-empty anchor using complition of all the anchors in the current buffer"
481 (let ((anchor
482 (completing-read "Anchor: " (moinmoin-list-anchors)
483 nil require-match
484 nil moinmoin-anchor-history)))
485 (when (string-equal anchor "")
486 (error "Empty anchor"))
487 anchor))
488
489 (defun moinmoin-insert-number-sign (&optional no-title)
490 (interactive "P")
491 "After `[' insert a reference to anchor inputed using completition,
492 If no argument given also insert the title of the section which contains
493 the anchor."
494 (cond
495 ((and (looking-back "\\[")
496 (not (get-text-property (point) 'moinmoin-verbatim)))
497 (let* ((anchor (moinmoin-completing-read-anchor "Anchor: "))
498 (title
499 (unless no-title
500 (condition-case nil
501 (moinmoin-get-anchored-header anchor)
502 (error (message "No header for anchor %s" anchor) nil)))))
503 (insert "#" anchor " ")
504 (if title
505 (insert title "]")
506 (insert "]") (backward-char))))
507 (t ; not after "["
508 (insert "#"))))
509
510 (defun moinmoin-insert-anchor ()
511 "Insert anchor (using the title if point is in a header)"
512 (interactive)
513 (cond
514 ((moinmoin-is-header)
515 (let ((anchor-name
516 (replace-regexp-in-string ; remove non-anchor symbols
517 "[^A-Za-z0-9]+" "-"
518 (match-string-no-properties 1) t t)))
519 (forward-line)
520 (insert "[[Anchor(" anchor-name ")]]\n")))
521 (t
522 (insert "[[Anchor()]]") (backward-char 3))))
523
524 (defun moinmoin-anchor-read-or-ask (&optional prompt)
525 "DWIM to get anchor: read [#... ] on current line (before point) or ask user."
526 (cond
527 ((and
528 (search-backward
529 "[#" (save-excursion (beginning-of-line) (point)) t)
530 (looking-at "\\[#\\([^]\n ]+\\)"))
531 (match-string-no-properties 1))
532 (t
533 (moinmoin-completing-read-anchor (or prompt "Anchor: ") t))))
534
535 (defun moinmoin-goto-anchor (&optional anchor)
536 "Go to anchor
537 If ANCHOR is nil (e.g., if called interactively) read reference
538 to it from the current line or ask user. So if there is an
539 anchor on the current line but you want to jump to something
540 different go to the beginning of the line first."
541 (interactive)
542 (unless anchor
543 (setq anchor (moinmoin-anchor-read-or-ask)))
544 (goto-char 1)
545 (search-forward (concat "[[Anchor(" anchor ")]]")))
546
547 (defun moinmoin-get-anchored-header (anchor)
548 "Get title of the section which contains ANCHOR"
549 (save-excursion
550 (moinmoin-goto-anchor anchor)
551 (search-backward-regexp "^=+ \\(.*\\) =+$" nil)
552 (match-string-no-properties 1)))
553
554 (defun moinmoin-insert-anchored-header (&optional to-kill-ring)
555 "Insert title of the section which contains anchor, with prefix save it to kill-ring"
556 (interactive "P")
557 (let ((header (moinmoin-get-anchored-header nil)))
558 (if to-kill-ring
559 (kill-new header)
560 (insert header))))
561
562
563 ;;; Setup
564 (define-derived-mode moinmoin-mode outline-mode "MoinMoin"
565 "Set major mode for editing MoinMoin pages"
566 (make-local-variable 'outline-regexp)
567 (setq outline-regexp "=+")
568 (make-local-variable 'outline-heading-end-regexp)
569 (setq outline-heading-end-regexp " =+\n")
570 (local-set-key "\"" 'moinmoin-insert-quote)
571 (local-set-key "-" 'moinmoin-insert-dash)
572 (local-set-key "(" 'moinmoin-insert-lparen)
573 (local-set-key ">" 'moinmoin-insert-greater-than)
574 (local-set-key "=" 'moinmoin-insert-equal)
575 (local-set-key "#" 'moinmoin-insert-number-sign)
576 (local-set-key (kbd "M-RET") 'moinmoin-insert-item)
577 (local-set-key (kbd "C-c a") 'moinmoin-insert-anchor)
578 (local-set-key (kbd "C-c g") 'moinmoin-goto-anchor)
579 (toggle-truncate-lines 0) ; do not truncate
580 (moinmoin-setup-font-lock)
581 (abbrev-mode 1)
582 (set-fill-column 65000)
583 (auto-fill-mode 0))
584
585 (add-to-list 'auto-mode-alist '("\\.wiki$" . moinmoin-mode))
586
587 (provide 'moinmoin-mode)
Attached Files
To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.You are not allowed to attach a file to this page.