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 (&ldquo; or &rdquo;)"
 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 "&ldquo;"))
 340    (t (insert "&rdquo;"))))
 341 
 342 (defun moinmoin-insert-dash ()
 343   "Insert different types of dashes.
 344 `----' and `-' stays unchanged
 345 `--' is converted to `&ndash;'
 346 `---' is converted to `&mdash;'
 347 `)--' is not changed'
 348 `<-' is converted to `&larr;'"
 349   (interactive)
 350   (cond
 351    ((get-text-property (point) 'moinmoin-verbatim)
 352     (insert "-"))
 353    ((looking-back "---\\|&mdash;")
 354     (replace-match "----" t t))
 355    ((looking-back "--\\|&ndash;")
 356     (replace-match "&mdash;" t t))
 357    ((looking-back ")-")
 358     (replace-match ")--" t t))
 359    ((looking-back "<")
 360     (replace-match "&larr;" t t))
 361    ((looking-back "-")
 362     (replace-match "&ndash;" t t))
 363    (t (insert "-"))))
 364 
 365 (defun moinmoin-insert-lparen ()
 366   "&ndash;( to --("
 367   (interactive)
 368   (cond
 369    ((get-text-property (point) 'moinmoin-verbatim)
 370     (insert "("))
 371    ((looking-back "&ndash;")
 372     (replace-match "--(" t t))
 373    (t (insert "("))))
 374 
 375 (defun moinmoin-insert-greater-than ()
 376   "-> to &rarr;"
 377   (interactive)
 378   (cond
 379    ((get-text-property (point) 'moinmoin-verbatim)
 380     (insert ">"))
 381    ((looking-back "-")
 382     (replace-match "&rarr;" 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.
  • [get | view] (2011-11-21 10:41:25, 22.7 KB) [[attachment:moinmoin-mode.el]]
 All files | Selected Files: delete move to page copy to page

You are not allowed to attach a file to this page.