Remove nobreak-space face definition
[markdown-mode/intrigeri.git] / markdown-mode.el
blob4aab1529973e04b3a5f9ab43e63178d199e196d0
1 ;;; markdown-mode.el --- Major mode to edit Markdown files in Emacs
3 ;; Copyright (C) 2007-2008 Jason Blevins
5 ;; Version: 1.6-dev
6 ;; Keywords: Markdown major mode
7 ;; Author: Jason Blevins <jrblevin@sdf.lonestar.org>
8 ;; URL: http://jblevins.org/projects/markdown-mode
10 ;; This file is not part of GNU Emacs.
12 ;; This program is free software; you can redistribute it and/or modify
13 ;; it under the terms of the GNU General Public License as published by
14 ;; the Free Software Foundation; either version 2, or (at your option)
15 ;; any later version.
17 ;; This program is distributed in the hope that it will be useful,
18 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 ;; GNU General Public License for more details.
22 ;; You should have received a copy of the GNU General Public License
23 ;; along with this program; if not, write to the Free Software
24 ;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 ;;; Commentary:
28 ;; markdown-mode is a major mode for editing [Markdown][]-formatted
29 ;; text files in GNU Emacs. markdown-mode is free software, licensed
30 ;; under the GNU GPL.
32 ;; [Markdown]: http://daringfireball.net/projects/markdown/
34 ;; The latest version is markdown-mode 1.5, released on October 11, 2007:
36 ;; * [markdown-mode.el][]
37 ;; * [Screenshot][]
38 ;; * [Release notes][]
40 ;; markdown-mode is also available in the Debian `emacs-goodies-el`
41 ;; package (beginning with revision 27.0-1).
43 ;; [markdown-mode.el]: http://code.jblevins.org/markdown-mode/markdown-mode.el
44 ;; [screenshot]: http://jblevins.org/projects/markdown-mode/screenshots/20071011-001.png
45 ;; [release notes]: http://jblevins.org/projects/markdown-mode/rev-1-5
47 ;;; Dependencies:
49 ;; markdown-mode requires easymenu, a standard package since GNU Emacs
50 ;; 19 and XEmacs 19, which provides a uniform interface for creating
51 ;; menus in GNU Emacs and XEmacs.
53 ;;; Installation:
55 ;; Make sure to place `markdown-mode.el` somewhere in the load-path and add
56 ;; the following lines to your `.emacs` file to associate markdown-mode
57 ;; with `.text` files:
59 ;; (autoload 'markdown-mode "markdown-mode.el"
60 ;; "Major mode for editing Markdown files" t)
61 ;; (setq auto-mode-alist
62 ;; (cons '("\\.text" . markdown-mode) auto-mode-alist))
64 ;; There is no consensus on an official file extension so change `.text` to
65 ;; `.mdwn`, `.md`, `.mdt`, or whatever you call your markdown files.
67 ;;; Usage:
69 ;; Although no configuration is necessary there are a few things that can
70 ;; be customized (`M-x customize-mode`).
72 ;; Keybindings are grouped by prefixes based on their function. For
73 ;; example, commands dealing with headers begin with `C-c C-t`. The
74 ;; primary commands in each group will are described below. You can
75 ;; obtain a list of all keybindings by pressing `C-c C-h`.
77 ;; * Anchors: `C-c C-a`
79 ;; `C-c C-a l` inserts inline links of the form `[text](url)`. If
80 ;; there is an active region, text in the region is used for the link
81 ;; text. `C-c C-a w` acts similarly for wiki links of the form
82 ;; `[[WikiLink]]`.
84 ;; * Commands: `C-c C-c`
86 ;; `C-c C-c m` will run Markdown on the current buffer and preview the
87 ;; output in another buffer while `C-c C-c p` runs Markdown on the
88 ;; current buffer and previews the output in a browser.
90 ;; `C-c C-c c` will check for undefined references. If there are any,
91 ;; a small buffer will open with a list. Selecting a reference from
92 ;; this list and pressing `RET` will insert a reference template at
93 ;; the end of the buffer.
95 ;; * Images: `C-c C-i`
97 ;; `C-c C-i i` inserts an image, using the active region (if any) as
98 ;; the alt text.
100 ;; * Physical styles: `C-c C-p`
102 ;; These commands all act on text in the active region, if any, and
103 ;; insert empty markup fragments otherwise. `C-c C-p b` makes the
104 ;; selected text bold, `C-c C-p f` formats the region as fixed-width
105 ;; text, and `C-c C-p i` is used for italic text.
107 ;; * Logical styles: `C-c C-s`
109 ;; These commands all act on text in the active region, if any, and
110 ;; insert empty markup fragments otherwise. Logical styles include
111 ;; blockquote (`C-c C-s b`), preformatted (`C-c C-s p`), code (`C-c C-s c`),
112 ;; emphasis (`C-c C-s e`), and strong (`C-c C-s s`).
114 ;; * Headers: `C-c C-t`
116 ;; All header commands use text in the active region, if any, as the
117 ;; header text. To insert an atx or hash style level-n header, press
118 ;; `C-c C-t n` where n is between 1 and 5. For a top-level setext or
119 ;; underline style header press `C-c C-t t` (mnemonic: title) and for
120 ;; a second-level underline-style header press `C-c C-t s`
121 ;; (mnemonic: section).
123 ;; * Other commands
125 ;; `C-c -` inserts a horizontal rule.
127 ;; Many of the commands described above behave differently depending on
128 ;; whether Transient Mark mode is enabled or not. When it makes sense,
129 ;; if Transient Mark mode is on and a region is active, the command
130 ;; applies to the text in the region (e.g., `C-c C-p b` makes the region
131 ;; bold). For users who prefer to work outside of Transient Mark mode,
132 ;; in Emacs 22 it can be enabled temporarily by pressing `C-SPC C-SPC`.
134 ;; When applicable, commands that specifically act on the region even
135 ;; outside of Transient Mark mode have the same keybinding as the with
136 ;; the exception of an additional `C-` prefix. For example,
137 ;; `markdown-insert-blockquote` is bound to `C-c C-s b` and only acts on
138 ;; the region in Transient Mark mode while `markdown-blockquote-region`
139 ;; is bound to `C-c C-s C-b` and always applies to the region (when
140 ;; nonempty).
142 ;;; Extensions:
144 ;; Besides supporting the basic Markdown syntax, markdown-mode also
145 ;; includes syntax highlighting for `[[Wiki Links]]` by default.
146 ;; Syntax highlighting for mathematical expressions written in LaTeX
147 ;; (only expressions denoted by `$..$`, `$$..$$`, or `\[..\]`) can be
148 ;; enabled by editing `markdown-mode.el` and changing
149 ;; `(defvar markdown-enable-itex nil)` to `(defvar markdown-enable-itex t)`.
151 ;;; Thanks:
153 ;; * Cyril Brulebois <cyril.brulebois@enst-bretagne.fr> for Debian packaging.
154 ;; * Conal Elliott <conal@conal.net> for a font-lock regexp patch.
155 ;; * Edward O'Connor <hober0@gmail.com> for a font-lock regexp fix.
156 ;; * Greg Bognar <greg_bognar@hms.harvard.edu> for menus and a patch.
157 ;; * Daniel Burrows <dburrows@debian.org> for filing Debian bug #456592.
158 ;; * Peter S. Galbraith <psg@debian.org> for maintaining emacs-goodies-el.
159 ;; * Dmitry Dzhus <mail@sphinx.net.ru> for reference checking functions.
161 ;;; Bugs:
163 ;; This mode has only been tested on Emacs 21.4 and 22.0. Please let me
164 ;; know if there are problems on other versions. If you find any bugs,
165 ;; such as syntax highlighting issues, please construct a test case and
166 ;; email me at <jrblevin@sdf.lonestar.org>.
170 ;;; Code:
172 (require 'easymenu)
174 ;;; User Customizable Variables ===============================================
176 ;; To enable LaTeX/itex syntax highlighting, change to
177 ;; (defvar markdown-enable-itex t)
178 (defvar markdown-enable-itex nil)
181 ;;; Customizable variables ====================================================
183 ;; Current revision
184 (defconst markdown-mode-version "1.6-dev")
186 ;; A hook for users to run their own code when the mode is loaded.
187 (defvar markdown-mode-hook nil)
190 ;;; Customizable variables ====================================================
192 (defgroup markdown nil
193 "Major mode for editing text files in Markdown format."
194 :prefix "markdown-"
195 :group 'wp
196 :link '(url-link "http://jblevins.org/projects/markdown-mode/"))
198 (defcustom markdown-command "markdown"
199 "Command to run markdown."
200 :group 'markdown
201 :type 'string)
203 (defcustom markdown-hr-length 5
204 "Length of horizonal rules."
205 :group 'markdown
206 :type 'integer)
208 (defcustom markdown-bold-underscore nil
209 "Use two underscores for bold instead of two asterisks."
210 :group 'markdown
211 :type 'boolean)
213 (defcustom markdown-italic-underscore nil
214 "Use underscores for italic instead of asterisks."
215 :group 'markdown
216 :type 'boolean)
219 ;;; Font lock =================================================================
221 (require 'font-lock)
223 (defgroup markdown-faces nil
224 "Faces used in Markdown Mode"
225 :group 'markdown
226 :group 'faces)
228 (defcustom markdown-italic-face 'font-lock-variable-name-face
229 "Italic text."
230 :group 'markdown-faces
231 :type '(face))
233 (defcustom markdown-bold-face 'font-lock-type-face
234 "Bold text"
235 :group 'markdown-faces
236 :type '(face))
238 (defcustom markdown-header-face 'font-lock-function-name-face
239 "Headers"
240 :group 'markdown-faces
241 :type '(face))
243 (defcustom markdown-inline-code-face 'font-lock-builtin-face
244 "Inline code"
245 :group 'markdown-faces
246 :type '(face))
248 (defcustom markdown-list-face 'font-lock-variable-name-face
249 "List item markers"
250 :group 'markdown-faces
251 :type '(face))
253 (defcustom markdown-blockquote-face 'font-lock-comment-face
254 "Blockquote sections and preformatted text"
255 :group 'markdown-faces
256 :type '(face))
258 (defcustom markdown-link-face 'font-lock-constant-face
259 "Link text"
260 :group 'markdown-faces
261 :type '(face))
263 (defcustom markdown-reference-face 'font-lock-type-face
264 "Link references"
265 :group 'markdown-faces
266 :type '(face))
268 (defcustom markdown-url-face 'font-lock-string-face
269 "URLs"
270 :group 'markdown-faces
271 :type '(face))
273 (defcustom markdown-math-face 'font-lock-builtin-face
274 "LaTeX expressions"
275 :group 'markdown-faces
276 :type '(face))
278 (defconst markdown-regex-link-inline
279 "\\(!?\\[[^]]*?\\]\\)\\(([^\\)]*)\\)"
280 "Regular expression for a [text](file) or an image link ![text](file)")
282 (defconst markdown-regex-link-reference
283 "\\(!?\\[[^]]+?\\]\\)[ ]?\\(\\[[^]]*?\\]\\)"
284 "Regular expression for a reference link [text][id]")
286 (defconst markdown-regex-reference-definition
287 "^ \\{0,3\\}\\(\\[.+?\\]\\): [ ]?\\(.*?\\)\\(\"[^\"]+?\"\\)?$"
288 "Regular expression for a link definition [id]: ...")
290 (defconst markdown-regex-header-atx
291 "^\\(#+ \\)\\(.*?\\)\\($\\| #+$\\)"
292 "Regular expression for atx-style (hash mark) headers")
294 (defconst markdown-regex-header-setext
295 "^\\(.*\\)\n\\(===+\\|---+\\)$"
296 "Regular expression for setext-style (underline) headers")
298 (defconst markdown-regex-hr
299 "^\\(\\*[ ]?\\*[ ]?\\*[ ]?[\\* ]*\\|-[ ]?-[ ]?-[--- ]*\\)$"
300 "Regular expression for matching Markdown horizontal rules")
302 (defconst markdown-regex-code
303 "\\(^\\|[^\\]\\)\\(\\(`\\{1,2\\}\\)\\([^ \\]\\|[^ ].*?[^ \\]\\)\\3\\)"
304 "Regular expression for matching inline code fragments")
306 (defconst markdown-regex-pre
307 "^ .*$"
308 "Regular expression for matching preformatted text sections")
310 (defconst markdown-regex-list
311 "^[ \t]*\\([0-9]+\\.\\|[\\*\\+-]\\) "
312 "Regular expression for matching list markers")
314 (defconst markdown-regex-bold
315 "\\(^\\|[^\\]\\)\\(\\([*_]\\{2\\}\\)\\(.\\|\n\\)*?[^\\ ]\\3\\)"
316 "Regular expression for matching bold text")
318 (defconst markdown-regex-italic
319 "\\(^\\|[^\\]\\)\\(\\([*_]\\)\\([^ \\]\\3\\|[^ ]\\(.\\|\n\\)*?[^\\ ]\\3\\)\\)"
320 "Regular expression for matching italic text")
322 (defconst markdown-regex-blockquote
323 "^>.*$"
324 "Regular expression for matching blockquote lines")
326 (defconst markdown-regex-line-break
327 " $"
328 "Regular expression for matching line breaks")
330 (defconst markdown-regex-wiki-link
331 "\\[\\[[^]]+\\]\\]"
332 "Regular expression for matching wiki links")
334 (defconst markdown-regex-uri
335 "<\\(acap\\|cid\\|data\\|dav\\|fax\\|file\\|ftp\\|gopher\\|http\\|https\\|imap\\|ldap\\|mailto\\|mid\\|modem\\|news\\|nfs\\|nntp\\|pop\\|prospero\\|rtsp\\|service\\|sip\\|tel\\|telnet\\|tip\\|urn\\|vemmi\\|wais\\)://[^>]*>"
336 "Regular expression for matching inline URIs")
338 (defconst markdown-regex-email
339 "<\\(\\sw\\|\\s_\\|\\s.\\)+@\\(\\sw\\|\\s_\\|\\s.\\)+>"
340 "Regular expression for matching inline email addresses")
342 (defconst markdown-regex-latex-expression
343 "\\(^\\|[^\\]\\)\\(\\$\\($\\([^\\$]\\|\\\\.\\)*\\$\\|\\([^\\$]\\|\\\\.\\)*\\)\\$\\)"
344 "Regular expression for itex $..$ or $$..$$ math mode expressions")
346 (defconst markdown-regex-latex-display
347 "^\\\\\\[\\(.\\|\n\\)*?\\\\\\]$"
348 "Regular expression for itex \[..\] display mode expressions")
350 (defconst markdown-mode-font-lock-keywords-basic
351 (list
352 (cons markdown-regex-code markdown-inline-code-face)
353 (cons markdown-regex-pre markdown-blockquote-face)
354 (cons markdown-regex-header-setext markdown-header-face)
355 (cons markdown-regex-header-atx markdown-header-face)
356 (cons markdown-regex-list markdown-list-face)
357 (cons markdown-regex-hr markdown-header-face)
358 (cons markdown-regex-link-inline
359 '((1 markdown-link-face t)
360 (2 markdown-url-face t)))
361 (cons markdown-regex-link-reference
362 '((1 markdown-link-face t)
363 (2 markdown-reference-face t)))
364 (cons markdown-regex-reference-definition
365 '((1 markdown-reference-face t)
366 (2 markdown-url-face t)
367 (3 markdown-link-face t)))
368 (cons markdown-regex-bold '(2 markdown-bold-face))
369 (cons markdown-regex-italic '(2 markdown-italic-face))
370 (cons markdown-regex-blockquote markdown-blockquote-face)
371 (cons markdown-regex-wiki-link markdown-link-face)
372 (cons markdown-regex-uri markdown-link-face)
373 (cons markdown-regex-email markdown-link-face))
374 "Syntax highlighting for Markdown files.")
377 ;; Includes additional Latex/itex/Instiki font lock keywords
378 (defconst markdown-mode-font-lock-keywords-itex
379 (append
380 (list
381 ;; itex math mode $..$ or $$..$$
382 (cons markdown-regex-latex-expression '(2 markdown-math-face))
383 ;; Display mode equations with brackets: \[ \]
384 (cons markdown-regex-latex-display markdown-math-face)
385 ;; Equation reference (eq:foo)
386 (cons "(eq:\\w+)" markdown-reference-face)
387 ;; Equation reference \eqref
388 (cons "\\\\eqref{\\w+}" markdown-reference-face))
389 markdown-mode-font-lock-keywords-basic)
390 "Syntax highlighting for Markdown, itex, and wiki expressions.")
393 (defvar markdown-mode-font-lock-keywords
394 (if markdown-enable-itex
395 markdown-mode-font-lock-keywords-itex
396 markdown-mode-font-lock-keywords-basic)
397 "Default highlighting expressions for Markdown mode")
401 ;;; Syntax Table ==============================================================
403 (defvar markdown-mode-syntax-table
404 (let ((markdown-mode-syntax-table (make-syntax-table)))
405 (modify-syntax-entry ?\" "w" markdown-mode-syntax-table)
406 markdown-mode-syntax-table)
407 "Syntax table for markdown-mode")
411 ;;; Element Insertion =========================================================
413 (defun markdown-wrap-or-insert (s1 s2)
414 "Insert the strings S1 and S2.
415 If Transient Mark mode is on and a region is active, wrap the strings S1
416 and S2 around the region."
417 (if (and transient-mark-mode mark-active)
418 (let ((a (region-beginning)) (b (region-end)))
419 (goto-char a)
420 (insert s1)
421 (goto-char (+ b (length s1)))
422 (insert s2))
423 (insert s1 s2)))
425 (defun markdown-insert-hr ()
426 "Inserts a horizonal rule."
427 (interactive)
428 (let (hr)
429 (dotimes (count (- markdown-hr-length 1) hr) ; Count to n - 1
430 (setq hr (concat "* " hr))) ; Build HR string
431 (setq hr (concat hr "*\n")) ; Add the n-th *
432 (insert hr)))
434 (defun markdown-insert-bold ()
435 "Inserts markup for a bold word or phrase.
436 If Transient Mark mode is on and a region is active, it is made bold."
437 (interactive)
438 (if markdown-bold-underscore
439 (markdown-wrap-or-insert "__" "__")
440 (markdown-wrap-or-insert "**" "**"))
441 (backward-char 2))
443 (defun markdown-insert-italic ()
444 "Inserts markup for an italic word or phrase.
445 If Transient Mark mode is on and a region is active, it is made italic."
446 (interactive)
447 (if markdown-italic-underscore
448 (markdown-wrap-or-insert "_" "_")
449 (markdown-wrap-or-insert "*" "*"))
450 (backward-char 1))
452 (defun markdown-insert-code ()
453 "Inserts markup for an inline code fragment.
454 If Transient Mark mode is on and a region is active, it is marked
455 as inline code."
456 (interactive)
457 (markdown-wrap-or-insert "`" "`")
458 (backward-char 1))
460 (defun markdown-insert-link ()
461 "Inserts an inline link of the form []().
462 If Transient Mark mode is on and a region is active, it is used
463 as the link text."
464 (interactive)
465 (markdown-wrap-or-insert "[" "]")
466 (insert "()")
467 (backward-char 1))
469 (defun markdown-insert-wiki-link ()
470 "Inserts a wiki link of the form [[WikiLink]].
471 If Transient Mark mode is on and a region is active, it is used
472 as the link text."
473 (interactive)
474 (markdown-wrap-or-insert "[[" "]]")
475 (backward-char 2))
477 (defun markdown-insert-image ()
478 "Inserts an inline image tag of the form ![]().
479 If Transient Mark mode is on and a region is active, it is used
480 as the alt text of the image."
481 (interactive)
482 (markdown-wrap-or-insert "![" "]")
483 (insert "()")
484 (backward-char 1))
486 (defun markdown-insert-header-1 ()
487 "Inserts a first level atx-style (hash mark) header.
488 If Transient Mark mode is on and a region is active, it is used
489 as the header text."
490 (interactive)
491 (markdown-insert-header 1))
493 (defun markdown-insert-header-2 ()
494 "Inserts a second level atx-style (hash mark) header.
495 If Transient Mark mode is on and a region is active, it is used
496 as the header text."
497 (interactive)
498 (markdown-insert-header 2))
500 (defun markdown-insert-header-3 ()
501 "Inserts a third level atx-style (hash mark) header.
502 If Transient Mark mode is on and a region is active, it is used
503 as the header text."
504 (interactive)
505 (markdown-insert-header 3))
507 (defun markdown-insert-header-4 ()
508 "Inserts a fourth level atx-style (hash mark) header.
509 If Transient Mark mode is on and a region is active, it is used
510 as the header text."
511 (interactive)
512 (markdown-insert-header 4))
514 (defun markdown-insert-header-5 ()
515 "Inserts a fifth level atx-style (hash mark) header.
516 If Transient Mark mode is on and a region is active, it is used
517 as the header text."
518 (interactive)
519 (markdown-insert-header 5))
521 (defun markdown-insert-header (n)
522 "Inserts an atx-style (hash mark) header.
523 With no prefix argument, insert a level-1 header. With prefix N,
524 insert a level-N header. If Transient Mark mode is on and the
525 region is active, it is used as the header text."
526 (interactive "p")
527 (unless n ; Test to see if n is defined
528 (setq n 1)) ; Default to level 1 header
529 (let (hdr)
530 (dotimes (count n hdr)
531 (setq hdr (concat "#" hdr))) ; Build a hash mark header string
532 (setq hdrl (concat hdr " "))
533 (setq hdrr (concat " " hdr))
534 (markdown-wrap-or-insert hdrl hdrr))
535 (backward-char (+ 1 n)))
537 (defun markdown-insert-title ()
538 "Insert a setext-style (underline) first level header.
539 If Transient Mark mode is on and a region is active, it is used
540 as the header text."
541 (interactive)
542 (if (and transient-mark-mode mark-active)
543 (let ((a (region-beginning))
544 (b (region-end))
545 (len 0)
546 (hdr))
547 (setq len (- b a))
548 (dotimes (count len hdr)
549 (setq hdr (concat "=" hdr))) ; Build a === title underline
550 (end-of-line)
551 (insert "\n" hdr "\n"))
552 (insert "\n==========\n")
553 (backward-char 12)))
555 (defun markdown-insert-section ()
556 "Insert a setext-style (underline) second level header.
557 If Transient Mark mode is on and a region is active, it is used
558 as the header text."
559 (interactive)
560 (if (and transient-mark-mode mark-active)
561 (let ((a (region-beginning))
562 (b (region-end))
563 (len 0)
564 (hdr))
565 (setq len (- b a))
566 (dotimes (count len hdr)
567 (setq hdr (concat "-" hdr))) ; Build a --- section underline
568 (end-of-line)
569 (insert "\n" hdr "\n"))
570 (insert "\n----------\n")
571 (backward-char 12)))
573 (defun markdown-insert-blockquote ()
574 "Start a blockquote section (or blockquote the region).
575 If Transient Mark mode is on and a region is active, it is used as
576 the blockquote text."
577 (interactive)
578 (if (and (boundp 'transient-mark-mode) transient-mark-mode mark-active)
579 (markdown-blockquote-region)
580 (insert "> ")))
582 (defun markdown-blockquote-region (beg end &optional arg)
583 "Blockquote the region."
584 (interactive "*r\nP")
585 (if mark-active
586 (perform-replace "^" "> " nil 1 nil nil nil beg end)))
588 (defun markdown-insert-pre ()
589 "Start a preformatted section (or apply to the region).
590 If Transient Mark mode is on and a region is active, it is marked
591 as preformatted text."
592 (interactive)
593 (if (and (boundp 'transient-mark-mode) transient-mark-mode mark-active)
594 (markdown-pre-region)
595 (insert " ")))
597 (defun markdown-pre-region (beg end &optional arg)
598 "Format the region as preformatted text."
599 (interactive "*r\nP")
600 (if mark-active
601 (perform-replace "^" " " nil 1 nil nil nil beg end)))
606 ;;; Keymap ====================================================================
608 (defvar markdown-mode-map
609 (let ((markdown-mode-map (make-keymap)))
610 ;; Element insertion
611 (define-key markdown-mode-map "\C-c\C-al" 'markdown-insert-link)
612 (define-key markdown-mode-map "\C-c\C-aw" 'markdown-insert-wiki-link)
613 (define-key markdown-mode-map "\C-c\C-ii" 'markdown-insert-image)
614 (define-key markdown-mode-map "\C-c\C-t1" 'markdown-insert-header-1)
615 (define-key markdown-mode-map "\C-c\C-t2" 'markdown-insert-header-2)
616 (define-key markdown-mode-map "\C-c\C-t3" 'markdown-insert-header-3)
617 (define-key markdown-mode-map "\C-c\C-t4" 'markdown-insert-header-4)
618 (define-key markdown-mode-map "\C-c\C-t5" 'markdown-insert-header-5)
619 (define-key markdown-mode-map "\C-c\C-pb" 'markdown-insert-bold)
620 (define-key markdown-mode-map "\C-c\C-ss" 'markdown-insert-bold)
621 (define-key markdown-mode-map "\C-c\C-pi" 'markdown-insert-italic)
622 (define-key markdown-mode-map "\C-c\C-se" 'markdown-insert-italic)
623 (define-key markdown-mode-map "\C-c\C-pf" 'markdown-insert-code)
624 (define-key markdown-mode-map "\C-c\C-sc" 'markdown-insert-code)
625 (define-key markdown-mode-map "\C-c\C-sb" 'markdown-insert-blockquote)
626 (define-key markdown-mode-map "\C-c\C-s\C-b" 'markdown-blockquote-region)
627 (define-key markdown-mode-map "\C-c\C-sp" 'markdown-insert-pre)
628 (define-key markdown-mode-map "\C-c\C-s\C-p" 'markdown-pre-region)
629 (define-key markdown-mode-map "\C-c-" 'markdown-insert-hr)
630 (define-key markdown-mode-map "\C-c\C-tt" 'markdown-insert-title)
631 (define-key markdown-mode-map "\C-c\C-ts" 'markdown-insert-section)
632 ;; Markdown functions
633 (define-key markdown-mode-map "\C-c\C-cm" 'markdown)
634 (define-key markdown-mode-map "\C-c\C-cp" 'markdown-preview)
635 ;; References
636 (define-key markdown-mode-map "\C-c\C-cc" 'markdown-check-refs)
637 markdown-mode-map)
638 "Keymap for Markdown major mode")
640 ;;; Menu ==================================================================
642 (easy-menu-define markdown-mode-menu markdown-mode-map
643 "Menu for Markdown mode"
644 '("Markdown"
645 ["Compile" markdown]
646 ["Preview" markdown-preview]
647 "---"
648 ("Headers (setext)"
649 ["Insert Title" markdown-insert-title]
650 ["Insert Section" markdown-insert-section])
651 ("Headers (atx)"
652 ["First level" markdown-insert-header-1]
653 ["Second level" markdown-insert-header-2]
654 ["Third level" markdown-insert-header-3]
655 ["Fourth level" markdown-insert-header-4]
656 ["Fifth level" markdown-insert-header-5])
657 "---"
658 ["Bold" markdown-insert-bold]
659 ["Italic" markdown-insert-italic]
660 ["Blockquote" markdown-insert-blockquote]
661 ["Preformatted" markdown-insert-pre]
662 ["Code" markdown-insert-code]
663 "---"
664 ["Insert inline link" markdown-insert-link]
665 ["Insert image" markdown-insert-image]
666 ["Insert horizontal rule" markdown-insert-hr]
667 "---"
668 ["Check references" markdown-check-refs]
669 "---"
670 ["Version" markdown-show-version]
675 ;;; References ================================================================
677 ;;; Undefined reference checking code by Dmitry Dzhus <mail@sphinx.net.ru>.
679 (defconst markdown-refcheck-buffer
680 "*Undefined references for %BUFFER%*"
681 "Name of buffer which will contain a list of undefined
682 references in `markdown-mode' buffer named %BUFFER%.")
684 (defun markdown-has-reference-definition (reference)
685 "Find out whether Markdown REFERENCE is defined.
687 REFERENCE should include the square brackets, like [this]."
688 (let ((reference (downcase reference)))
689 (save-excursion
690 (goto-char (point-min))
691 (catch 'found
692 (while (re-search-forward markdown-regex-reference-definition nil t)
693 (when (string= reference (downcase (match-string-no-properties 1)))
694 (throw 'found t)))))))
696 (defun markdown-get-undefined-refs ()
697 "Return a list of undefined Markdown references.
699 Result is an alist of pairs (reference . occurencies), where
700 occurencies is itself another alist of pairs (label .
701 line-number).
703 For example, an alist corresponding to [Nice editor][Emacs] at line 12,
704 \[GNU Emacs][Emacs] at line 45 and [manual][elisp] at line 127 is
705 \((\"[emacs]\" (\"[Nice editor]\" . 12) (\"[GNU Emacs]\" . 45)) (\"[elisp]\" (\"[manual]\" . 127)))."
706 (let ((missing))
707 (save-excursion
708 (goto-char (point-min))
709 (while
710 (re-search-forward markdown-regex-link-reference nil t)
711 (let* ((label (match-string-no-properties 1))
712 (reference (match-string-no-properties 2))
713 (target (downcase (if (string= reference "[]") label reference))))
714 (unless (markdown-has-reference-definition target)
715 (let ((entry (assoc target missing)))
716 (if (not entry)
717 (add-to-list 'missing (cons target
718 (list (cons label (line-number-at-pos)))) t)
719 (setcdr entry
720 (append (cdr entry) (list (cons label (line-number-at-pos))))))))))
721 missing)))
723 (defun markdown-add-missing-ref-definition (ref buffer &optional recheck)
724 "Add blank REF definition to the end of BUFFER.
726 REF is a Markdown reference in square brackets, like \"[lisp-history]\".
728 When RECHECK is non-nil, BUFFER gets rechecked for undefined
729 references so that REF disappears from the list of those links."
730 (with-current-buffer buffer
731 (when (not (eq major-mode 'markdown-mode))
732 (error "Not available in current mdoe"))
733 (goto-char (point-max))
734 (indent-new-comment-line)
735 (insert (concat ref ": ")))
736 (switch-to-buffer-other-window buffer)
737 (goto-char (point-max))
738 (when recheck
739 (markdown-check-refs t)))
741 ;; Button which adds an empty Markdown reference definition to the end
742 ;; of buffer specified as its 'target-buffer property. Reference name
743 ;; is button's label
744 (define-button-type 'markdown-ref-button
745 'help-echo "Push to create an empty reference definition"
746 'face 'bold
747 'action (lambda (b)
748 (markdown-add-missing-ref-definition
749 (button-label b) (button-get b 'target-buffer) t)))
751 ;; Button jumping to line in buffer specified as its 'target-buffer
752 ;; property. Line number is button's 'line property.
753 (define-button-type 'goto-line-button
754 'help-echo "Push to go to this line"
755 'face 'italic
756 'action (lambda (b)
757 (message (button-get b 'buffer))
758 (switch-to-buffer-other-window (button-get b 'target-buffer))
759 (goto-line (button-get b 'target-line))))
761 (defun markdown-check-refs (&optional silent)
762 "Show all undefined Markdown references in current `markdown-mode' buffer.
764 If SILENT is non-nil, do not message anything when no undefined
765 references found.
767 Links which have empty reference definitions are considered to be
768 defined."
769 (interactive "P")
770 (when (not (eq major-mode 'markdown-mode))
771 (error "Not available in current mode"))
772 (let ((oldbuf (current-buffer))
773 (refs (markdown-get-undefined-refs))
774 (refbuf (get-buffer-create (replace-regexp-in-string
775 "%BUFFER%" (buffer-name)
776 markdown-refcheck-buffer t))))
777 (if (null refs)
778 (progn
779 (when (not silent)
780 (message "No undefined references found"))
781 (kill-buffer refbuf))
782 (with-current-buffer refbuf
783 (when view-mode
784 (View-exit-and-edit))
785 (erase-buffer)
786 (insert "Following references lack definitions:")
787 (newline 2)
788 (dolist (ref refs)
789 (let ((button-label (format "%s" (car ref))))
790 (insert-text-button button-label
791 :type 'markdown-ref-button
792 'target-buffer oldbuf)
793 (insert " (")
794 (dolist (occurency (cdr ref))
795 (let ((line (cdr occurency)))
796 (insert-button (number-to-string line)
797 :type 'goto-line-button
798 'target-buffer oldbuf
799 'target-line line)
800 (insert " "))) (delete-backward-char 1)
801 (insert ")")
802 (newline))))
803 (view-buffer-other-window refbuf)
804 (goto-line 4))))
807 ;;; Commands ==================================================================
809 (defun markdown ()
810 "Run markdown on the current buffer and preview the output in another buffer."
811 (interactive)
812 (if (and (boundp 'transient-mark-mode) transient-mark-mode mark-active)
813 (shell-command-on-region (region-beginning) (region-end) markdown-command
814 "*markdown-output*" nil)
815 (shell-command-on-region (point-min) (point-max) markdown-command
816 "*markdown-output*" nil)))
818 (defun markdown-preview ()
819 "Run markdown on the current buffer and preview the output in a browser."
820 (interactive)
821 (markdown)
822 (browse-url-of-buffer "*markdown-output*"))
826 ;;; Mode definition ==========================================================
828 (defun markdown-show-version ()
829 "Show the version number in the minibuffer."
830 (interactive)
831 (message "markdown-mode, version %s" markdown-mode-version))
833 (define-derived-mode markdown-mode text-mode "Markdown"
834 "Major mode for editing Markdown files."
835 ;; Font lock.
836 (set (make-local-variable 'font-lock-defaults)
837 '(markdown-mode-font-lock-keywords))
838 (set (make-local-variable 'font-lock-multiline) t)
839 ;; For menu support in XEmacs
840 (easy-menu-add markdown-mode-menu markdown-mode-map))
842 ;(add-to-list 'auto-mode-alist '("\\.text$" . markdown-mode))
844 (provide 'markdown-mode)
846 ;;; markdown-mode.el ends here