1 ;;; markdown-mode.el --- Major mode to edit Markdown files in Emacs
3 ;; Copyright (C) 2007-2008 Jason Blevins
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)
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.
28 ;; markdown-mode is a major mode for editing [Markdown][]-formatted
29 ;; text files in GNU Emacs. markdown-mode is free software, licensed
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][]
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
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.
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.
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
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 of undefined references and
92 ;; the line numbers on which they appear. In Emacs 22 and greater,
93 ;; selecting a reference from this list and pressing `RET` will insert
94 ;; an empty reference definition at the end of the buffer. Similarly,
95 ;; selecting the line number will jump to the corresponding line.
97 ;; * Images: `C-c C-i`
99 ;; `C-c C-i i` inserts an image, using the active region (if any) as
102 ;; * Physical styles: `C-c C-p`
104 ;; These commands all act on text in the active region, if any, and
105 ;; insert empty markup fragments otherwise. `C-c C-p b` makes the
106 ;; selected text bold, `C-c C-p f` formats the region as fixed-width
107 ;; text, and `C-c C-p i` is used for italic text.
109 ;; * Logical styles: `C-c C-s`
111 ;; These commands all act on text in the active region, if any, and
112 ;; insert empty markup fragments otherwise. Logical styles include
113 ;; blockquote (`C-c C-s b`), preformatted (`C-c C-s p`), code (`C-c C-s c`),
114 ;; emphasis (`C-c C-s e`), and strong (`C-c C-s s`).
116 ;; * Headers: `C-c C-t`
118 ;; All header commands use text in the active region, if any, as the
119 ;; header text. To insert an atx or hash style level-n header, press
120 ;; `C-c C-t n` where n is between 1 and 5. For a top-level setext or
121 ;; underline style header press `C-c C-t t` (mnemonic: title) and for
122 ;; a second-level underline-style header press `C-c C-t s`
123 ;; (mnemonic: section).
127 ;; `C-c -` inserts a horizontal rule.
129 ;; Many of the commands described above behave differently depending on
130 ;; whether Transient Mark mode is enabled or not. When it makes sense,
131 ;; if Transient Mark mode is on and a region is active, the command
132 ;; applies to the text in the region (e.g., `C-c C-p b` makes the region
133 ;; bold). For users who prefer to work outside of Transient Mark mode,
134 ;; in Emacs 22 it can be enabled temporarily by pressing `C-SPC C-SPC`.
136 ;; When applicable, commands that specifically act on the region even
137 ;; outside of Transient Mark mode have the same keybinding as the with
138 ;; the exception of an additional `C-` prefix. For example,
139 ;; `markdown-insert-blockquote` is bound to `C-c C-s b` and only acts on
140 ;; the region in Transient Mark mode while `markdown-blockquote-region`
141 ;; is bound to `C-c C-s C-b` and always applies to the region (when
146 ;; Besides supporting the basic Markdown syntax, markdown-mode also
147 ;; includes syntax highlighting for `[[Wiki Links]]` by default.
148 ;; Syntax highlighting for mathematical expressions written in LaTeX
149 ;; (only expressions denoted by `$..$`, `$$..$$`, or `\[..\]`) can be
150 ;; enabled by editing `markdown-mode.el` and changing
151 ;; `(defvar markdown-enable-itex nil)` to `(defvar markdown-enable-itex t)`.
155 ;; * Cyril Brulebois <cyril.brulebois@enst-bretagne.fr> for Debian packaging.
156 ;; * Conal Elliott <conal@conal.net> for a font-lock regexp patch.
157 ;; * Edward O'Connor <hober0@gmail.com> for a font-lock regexp fix.
158 ;; * Greg Bognar <greg_bognar@hms.harvard.edu> for menus and a patch.
159 ;; * Daniel Burrows <dburrows@debian.org> for filing Debian bug #456592.
160 ;; * Peter S. Galbraith <psg@debian.org> for maintaining emacs-goodies-el.
161 ;; * Dmitry Dzhus <mail@sphinx.net.ru> for reference checking functions.
165 ;; This mode has only been tested on Emacs 21.4 and 22.0. Please let me
166 ;; know if there are problems on other versions. If you find any bugs,
167 ;; such as syntax highlighting issues, please construct a test case and
168 ;; email me at <jrblevin@sdf.lonestar.org>.
176 ;;; User Customizable Variables ===============================================
178 ;; To enable LaTeX/itex syntax highlighting, change to
179 ;; (defvar markdown-enable-itex t)
180 (defvar markdown-enable-itex nil
)
183 ;;; Customizable variables ====================================================
186 (defconst markdown-mode-version
"1.6-dev")
188 ;; A hook for users to run their own code when the mode is loaded.
189 (defvar markdown-mode-hook nil
)
192 ;;; Customizable variables ====================================================
194 (defgroup markdown nil
195 "Major mode for editing text files in Markdown format."
198 :link
'(url-link "http://jblevins.org/projects/markdown-mode/"))
200 (defcustom markdown-command
"markdown"
201 "Command to run markdown."
205 (defcustom markdown-hr-length
5
206 "Length of horizonal rules."
210 (defcustom markdown-bold-underscore nil
211 "Use two underscores for bold instead of two asterisks."
215 (defcustom markdown-italic-underscore nil
216 "Use underscores for italic instead of asterisks."
221 ;;; Font lock =================================================================
225 (defgroup markdown-faces nil
226 "Faces used in Markdown Mode"
230 (defcustom markdown-italic-face
'font-lock-variable-name-face
232 :group
'markdown-faces
235 (defcustom markdown-bold-face
'font-lock-type-face
237 :group
'markdown-faces
240 (defcustom markdown-header-face
'font-lock-function-name-face
242 :group
'markdown-faces
245 (defcustom markdown-inline-code-face
'font-lock-builtin-face
247 :group
'markdown-faces
250 (defcustom markdown-list-face
'font-lock-variable-name-face
252 :group
'markdown-faces
255 (defcustom markdown-blockquote-face
'font-lock-comment-face
256 "Blockquote sections and preformatted text"
257 :group
'markdown-faces
260 (defcustom markdown-link-face
'font-lock-constant-face
262 :group
'markdown-faces
265 (defcustom markdown-reference-face
'font-lock-type-face
267 :group
'markdown-faces
270 (defcustom markdown-url-face
'font-lock-string-face
272 :group
'markdown-faces
275 (defcustom markdown-math-face
'font-lock-builtin-face
277 :group
'markdown-faces
280 (defconst markdown-regex-link-inline
281 "\\(!?\\[[^]]*?\\]\\)\\(([^\\)]*)\\)"
282 "Regular expression for a [text](file) or an image link ![text](file)")
284 (defconst markdown-regex-link-reference
285 "\\(!?\\[[^]]+?\\]\\)[ ]?\\(\\[[^]]*?\\]\\)"
286 "Regular expression for a reference link [text][id]")
288 (defconst markdown-regex-reference-definition
289 "^ \\{0,3\\}\\(\\[.+?\\]\\): [ ]?\\(.*?\\)\\(\"[^\"]+?\"\\)?$"
290 "Regular expression for a link definition [id]: ...")
292 (defconst markdown-regex-header-atx
293 "^\\(#+ \\)\\(.*?\\)\\($\\| #+$\\)"
294 "Regular expression for atx-style (hash mark) headers")
296 (defconst markdown-regex-header-setext
297 "^\\(.*\\)\n\\(===+\\|---+\\)$"
298 "Regular expression for setext-style (underline) headers")
300 (defconst markdown-regex-hr
301 "^\\(\\*[ ]?\\*[ ]?\\*[ ]?[\\* ]*\\|-[ ]?-[ ]?-[--- ]*\\)$"
302 "Regular expression for matching Markdown horizontal rules")
304 (defconst markdown-regex-code
305 "\\(^\\|[^\\]\\)\\(\\(`\\{1,2\\}\\)\\([^ \\]\\|[^ ].*?[^ \\]\\)\\3\\)"
306 "Regular expression for matching inline code fragments")
308 (defconst markdown-regex-pre
310 "Regular expression for matching preformatted text sections")
312 (defconst markdown-regex-list
313 "^[ \t]*\\([0-9]+\\.\\|[\\*\\+-]\\) "
314 "Regular expression for matching list markers")
316 (defconst markdown-regex-bold
317 "\\(^\\|[^\\]\\)\\(\\([*_]\\{2\\}\\)\\(.\\|\n\\)*?[^\\ ]\\3\\)"
318 "Regular expression for matching bold text")
320 (defconst markdown-regex-italic
321 "\\(^\\|[^\\]\\)\\(\\([*_]\\)\\([^ \\]\\3\\|[^ ]\\(.\\|\n\\)*?[^\\ ]\\3\\)\\)"
322 "Regular expression for matching italic text")
324 (defconst markdown-regex-blockquote
326 "Regular expression for matching blockquote lines")
328 (defconst markdown-regex-line-break
330 "Regular expression for matching line breaks")
332 (defconst markdown-regex-wiki-link
334 "Regular expression for matching wiki links")
336 (defconst markdown-regex-uri
337 "<\\(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\\)://[^>]*>"
338 "Regular expression for matching inline URIs")
340 (defconst markdown-regex-email
341 "<\\(\\sw\\|\\s_\\|\\s.\\)+@\\(\\sw\\|\\s_\\|\\s.\\)+>"
342 "Regular expression for matching inline email addresses")
344 (defconst markdown-regex-latex-expression
345 "\\(^\\|[^\\]\\)\\(\\$\\($\\([^\\$]\\|\\\\.\\)*\\$\\|\\([^\\$]\\|\\\\.\\)*\\)\\$\\)"
346 "Regular expression for itex $..$ or $$..$$ math mode expressions")
348 (defconst markdown-regex-latex-display
349 "^\\\\\\[\\(.\\|\n\\)*?\\\\\\]$"
350 "Regular expression for itex \[..\] display mode expressions")
352 (defconst markdown-mode-font-lock-keywords-basic
354 (cons markdown-regex-code markdown-inline-code-face
)
355 (cons markdown-regex-pre markdown-blockquote-face
)
356 (cons markdown-regex-header-setext markdown-header-face
)
357 (cons markdown-regex-header-atx markdown-header-face
)
358 (cons markdown-regex-list markdown-list-face
)
359 (cons markdown-regex-hr markdown-header-face
)
360 (cons markdown-regex-link-inline
361 '((1 markdown-link-face t
)
362 (2 markdown-url-face t
)))
363 (cons markdown-regex-link-reference
364 '((1 markdown-link-face t
)
365 (2 markdown-reference-face t
)))
366 (cons markdown-regex-reference-definition
367 '((1 markdown-reference-face t
)
368 (2 markdown-url-face t
)
369 (3 markdown-link-face t
)))
370 (cons markdown-regex-bold
'(2 markdown-bold-face
))
371 (cons markdown-regex-italic
'(2 markdown-italic-face
))
372 (cons markdown-regex-blockquote markdown-blockquote-face
)
373 (cons markdown-regex-wiki-link markdown-link-face
)
374 (cons markdown-regex-uri markdown-link-face
)
375 (cons markdown-regex-email markdown-link-face
))
376 "Syntax highlighting for Markdown files.")
379 ;; Includes additional Latex/itex/Instiki font lock keywords
380 (defconst markdown-mode-font-lock-keywords-itex
383 ;; itex math mode $..$ or $$..$$
384 (cons markdown-regex-latex-expression
'(2 markdown-math-face
))
385 ;; Display mode equations with brackets: \[ \]
386 (cons markdown-regex-latex-display markdown-math-face
)
387 ;; Equation reference (eq:foo)
388 (cons "(eq:\\w+)" markdown-reference-face
)
389 ;; Equation reference \eqref
390 (cons "\\\\eqref{\\w+}" markdown-reference-face
))
391 markdown-mode-font-lock-keywords-basic
)
392 "Syntax highlighting for Markdown, itex, and wiki expressions.")
395 (defvar markdown-mode-font-lock-keywords
396 (if markdown-enable-itex
397 markdown-mode-font-lock-keywords-itex
398 markdown-mode-font-lock-keywords-basic
)
399 "Default highlighting expressions for Markdown mode")
403 ;;; Syntax Table ==============================================================
405 (defvar markdown-mode-syntax-table
406 (let ((markdown-mode-syntax-table (make-syntax-table)))
407 (modify-syntax-entry ?
\" "w" markdown-mode-syntax-table
)
408 markdown-mode-syntax-table
)
409 "Syntax table for markdown-mode")
413 ;;; Element Insertion =========================================================
415 (defun markdown-wrap-or-insert (s1 s2
)
416 "Insert the strings S1 and S2.
417 If Transient Mark mode is on and a region is active, wrap the strings S1
418 and S2 around the region."
419 (if (and transient-mark-mode mark-active
)
420 (let ((a (region-beginning)) (b (region-end)))
423 (goto-char (+ b
(length s1
)))
427 (defun markdown-insert-hr ()
428 "Inserts a horizonal rule."
431 (dotimes (count (- markdown-hr-length
1) hr
) ; Count to n - 1
432 (setq hr
(concat "* " hr
))) ; Build HR string
433 (setq hr
(concat hr
"*\n")) ; Add the n-th *
436 (defun markdown-insert-bold ()
437 "Inserts markup for a bold word or phrase.
438 If Transient Mark mode is on and a region is active, it is made bold."
440 (if markdown-bold-underscore
441 (markdown-wrap-or-insert "__" "__")
442 (markdown-wrap-or-insert "**" "**"))
445 (defun markdown-insert-italic ()
446 "Inserts markup for an italic word or phrase.
447 If Transient Mark mode is on and a region is active, it is made italic."
449 (if markdown-italic-underscore
450 (markdown-wrap-or-insert "_" "_")
451 (markdown-wrap-or-insert "*" "*"))
454 (defun markdown-insert-code ()
455 "Inserts markup for an inline code fragment.
456 If Transient Mark mode is on and a region is active, it is marked
459 (markdown-wrap-or-insert "`" "`")
462 (defun markdown-insert-link ()
463 "Inserts an inline link of the form []().
464 If Transient Mark mode is on and a region is active, it is used
467 (markdown-wrap-or-insert "[" "]")
471 (defun markdown-insert-wiki-link ()
472 "Inserts a wiki link of the form [[WikiLink]].
473 If Transient Mark mode is on and a region is active, it is used
476 (markdown-wrap-or-insert "[[" "]]")
479 (defun markdown-insert-image ()
480 "Inserts an inline image tag of the form ![]().
481 If Transient Mark mode is on and a region is active, it is used
482 as the alt text of the image."
484 (markdown-wrap-or-insert "![" "]")
488 (defun markdown-insert-header-1 ()
489 "Inserts a first level atx-style (hash mark) header.
490 If Transient Mark mode is on and a region is active, it is used
493 (markdown-insert-header 1))
495 (defun markdown-insert-header-2 ()
496 "Inserts a second level atx-style (hash mark) header.
497 If Transient Mark mode is on and a region is active, it is used
500 (markdown-insert-header 2))
502 (defun markdown-insert-header-3 ()
503 "Inserts a third level atx-style (hash mark) header.
504 If Transient Mark mode is on and a region is active, it is used
507 (markdown-insert-header 3))
509 (defun markdown-insert-header-4 ()
510 "Inserts a fourth level atx-style (hash mark) header.
511 If Transient Mark mode is on and a region is active, it is used
514 (markdown-insert-header 4))
516 (defun markdown-insert-header-5 ()
517 "Inserts a fifth level atx-style (hash mark) header.
518 If Transient Mark mode is on and a region is active, it is used
521 (markdown-insert-header 5))
523 (defun markdown-insert-header (n)
524 "Inserts an atx-style (hash mark) header.
525 With no prefix argument, insert a level-1 header. With prefix N,
526 insert a level-N header. If Transient Mark mode is on and the
527 region is active, it is used as the header text."
529 (unless n
; Test to see if n is defined
530 (setq n
1)) ; Default to level 1 header
532 (dotimes (count n hdr
)
533 (setq hdr
(concat "#" hdr
))) ; Build a hash mark header string
534 (setq hdrl
(concat hdr
" "))
535 (setq hdrr
(concat " " hdr
))
536 (markdown-wrap-or-insert hdrl hdrr
))
537 (backward-char (+ 1 n
)))
539 (defun markdown-insert-title ()
540 "Insert a setext-style (underline) first level header.
541 If Transient Mark mode is on and a region is active, it is used
544 (if (and transient-mark-mode mark-active
)
545 (let ((a (region-beginning))
550 (dotimes (count len hdr
)
551 (setq hdr
(concat "=" hdr
))) ; Build a === title underline
553 (insert "\n" hdr
"\n"))
554 (insert "\n==========\n")
557 (defun markdown-insert-section ()
558 "Insert a setext-style (underline) second level header.
559 If Transient Mark mode is on and a region is active, it is used
562 (if (and transient-mark-mode mark-active
)
563 (let ((a (region-beginning))
568 (dotimes (count len hdr
)
569 (setq hdr
(concat "-" hdr
))) ; Build a --- section underline
571 (insert "\n" hdr
"\n"))
572 (insert "\n----------\n")
575 (defun markdown-insert-blockquote ()
576 "Start a blockquote section (or blockquote the region).
577 If Transient Mark mode is on and a region is active, it is used as
578 the blockquote text."
580 (if (and (boundp 'transient-mark-mode
) transient-mark-mode mark-active
)
581 (markdown-blockquote-region)
584 (defun markdown-blockquote-region (beg end
&optional arg
)
585 "Blockquote the region."
586 (interactive "*r\nP")
588 (perform-replace "^" "> " nil
1 nil nil nil beg end
)))
590 (defun markdown-insert-pre ()
591 "Start a preformatted section (or apply to the region).
592 If Transient Mark mode is on and a region is active, it is marked
593 as preformatted text."
595 (if (and (boundp 'transient-mark-mode
) transient-mark-mode mark-active
)
596 (markdown-pre-region)
599 (defun markdown-pre-region (beg end
&optional arg
)
600 "Format the region as preformatted text."
601 (interactive "*r\nP")
603 (perform-replace "^" " " nil
1 nil nil nil beg end
)))
608 ;;; Keymap ====================================================================
610 (defvar markdown-mode-map
611 (let ((markdown-mode-map (make-keymap)))
613 (define-key markdown-mode-map
"\C-c\C-al" 'markdown-insert-link
)
614 (define-key markdown-mode-map
"\C-c\C-aw" 'markdown-insert-wiki-link
)
615 (define-key markdown-mode-map
"\C-c\C-ii" 'markdown-insert-image
)
616 (define-key markdown-mode-map
"\C-c\C-t1" 'markdown-insert-header-1
)
617 (define-key markdown-mode-map
"\C-c\C-t2" 'markdown-insert-header-2
)
618 (define-key markdown-mode-map
"\C-c\C-t3" 'markdown-insert-header-3
)
619 (define-key markdown-mode-map
"\C-c\C-t4" 'markdown-insert-header-4
)
620 (define-key markdown-mode-map
"\C-c\C-t5" 'markdown-insert-header-5
)
621 (define-key markdown-mode-map
"\C-c\C-pb" 'markdown-insert-bold
)
622 (define-key markdown-mode-map
"\C-c\C-ss" 'markdown-insert-bold
)
623 (define-key markdown-mode-map
"\C-c\C-pi" 'markdown-insert-italic
)
624 (define-key markdown-mode-map
"\C-c\C-se" 'markdown-insert-italic
)
625 (define-key markdown-mode-map
"\C-c\C-pf" 'markdown-insert-code
)
626 (define-key markdown-mode-map
"\C-c\C-sc" 'markdown-insert-code
)
627 (define-key markdown-mode-map
"\C-c\C-sb" 'markdown-insert-blockquote
)
628 (define-key markdown-mode-map
"\C-c\C-s\C-b" 'markdown-blockquote-region
)
629 (define-key markdown-mode-map
"\C-c\C-sp" 'markdown-insert-pre
)
630 (define-key markdown-mode-map
"\C-c\C-s\C-p" 'markdown-pre-region
)
631 (define-key markdown-mode-map
"\C-c-" 'markdown-insert-hr
)
632 (define-key markdown-mode-map
"\C-c\C-tt" 'markdown-insert-title
)
633 (define-key markdown-mode-map
"\C-c\C-ts" 'markdown-insert-section
)
634 ;; Markdown functions
635 (define-key markdown-mode-map
"\C-c\C-cm" 'markdown
)
636 (define-key markdown-mode-map
"\C-c\C-cp" 'markdown-preview
)
638 (define-key markdown-mode-map
"\C-c\C-cc" 'markdown-check-refs
)
640 "Keymap for Markdown major mode")
642 ;;; Menu ==================================================================
644 (easy-menu-define markdown-mode-menu markdown-mode-map
645 "Menu for Markdown mode"
648 ["Preview" markdown-preview
]
651 ["Insert Title" markdown-insert-title
]
652 ["Insert Section" markdown-insert-section
])
654 ["First level" markdown-insert-header-1
]
655 ["Second level" markdown-insert-header-2
]
656 ["Third level" markdown-insert-header-3
]
657 ["Fourth level" markdown-insert-header-4
]
658 ["Fifth level" markdown-insert-header-5
])
660 ["Bold" markdown-insert-bold
]
661 ["Italic" markdown-insert-italic
]
662 ["Blockquote" markdown-insert-blockquote
]
663 ["Preformatted" markdown-insert-pre
]
664 ["Code" markdown-insert-code
]
666 ["Insert inline link" markdown-insert-link
]
667 ["Insert image" markdown-insert-image
]
668 ["Insert horizontal rule" markdown-insert-hr
]
670 ["Check references" markdown-check-refs
]
672 ["Version" markdown-show-version
]
677 ;;; References ================================================================
679 ;;; Undefined reference checking code by Dmitry Dzhus <mail@sphinx.net.ru>.
681 (defconst markdown-refcheck-buffer
682 "*Undefined references for %BUFFER%*"
683 "Name of buffer which will contain a list of undefined
684 references in `markdown-mode' buffer named %BUFFER%.")
686 (defun markdown-has-reference-definition (reference)
687 "Find out whether Markdown REFERENCE is defined.
689 REFERENCE should include the square brackets, like [this]."
690 (let ((reference (downcase reference
)))
692 (goto-char (point-min))
694 (while (re-search-forward markdown-regex-reference-definition nil t
)
695 (when (string= reference
(downcase (match-string-no-properties 1)))
696 (throw 'found t
)))))))
698 (defun markdown-get-undefined-refs ()
699 "Return a list of undefined Markdown references.
701 Result is an alist of pairs (reference . occurencies), where
702 occurencies is itself another alist of pairs (label .
705 For example, an alist corresponding to [Nice editor][Emacs] at line 12,
706 \[GNU Emacs][Emacs] at line 45 and [manual][elisp] at line 127 is
707 \((\"[emacs]\" (\"[Nice editor]\" . 12) (\"[GNU Emacs]\" . 45)) (\"[elisp]\" (\"[manual]\" . 127)))."
710 (goto-char (point-min))
712 (re-search-forward markdown-regex-link-reference nil t
)
713 (let* ((label (match-string-no-properties 1))
714 (reference (match-string-no-properties 2))
715 (target (downcase (if (string= reference
"[]") label reference
))))
716 (unless (markdown-has-reference-definition target
)
717 (let ((entry (assoc target missing
)))
719 (add-to-list 'missing
(cons target
720 (list (cons label
(markdown-line-number-at-pos)))) t
)
722 (append (cdr entry
) (list (cons label
(markdown-line-number-at-pos))))))))))
725 (defun markdown-add-missing-ref-definition (ref buffer
&optional recheck
)
726 "Add blank REF definition to the end of BUFFER.
728 REF is a Markdown reference in square brackets, like \"[lisp-history]\".
730 When RECHECK is non-nil, BUFFER gets rechecked for undefined
731 references so that REF disappears from the list of those links."
732 (with-current-buffer buffer
733 (when (not (eq major-mode
'markdown-mode
))
734 (error "Not available in current mdoe"))
735 (goto-char (point-max))
736 (indent-new-comment-line)
737 (insert (concat ref
": ")))
738 (switch-to-buffer-other-window buffer
)
739 (goto-char (point-max))
741 (markdown-check-refs t
)))
743 ;; Button which adds an empty Markdown reference definition to the end
744 ;; of buffer specified as its 'target-buffer property. Reference name
746 (when (>= emacs-major-version
22)
747 (define-button-type 'markdown-ref-button
748 'help-echo
"Push to create an empty reference definition"
751 (markdown-add-missing-ref-definition
752 (button-label b
) (button-get b
'target-buffer
) t
))))
754 ;; Button jumping to line in buffer specified as its 'target-buffer
755 ;; property. Line number is button's 'line property.
756 (when (>= emacs-major-version
22)
757 (define-button-type 'goto-line-button
758 'help-echo
"Push to go to this line"
761 (message (button-get b
'buffer
))
762 (switch-to-buffer-other-window (button-get b
'target-buffer
))
763 (goto-line (button-get b
'target-line
)))))
765 (defun markdown-check-refs (&optional silent
)
766 "Show all undefined Markdown references in current `markdown-mode' buffer.
768 If SILENT is non-nil, do not message anything when no undefined
771 Links which have empty reference definitions are considered to be
774 (when (not (eq major-mode
'markdown-mode
))
775 (error "Not available in current mode"))
776 (let ((oldbuf (current-buffer))
777 (refs (markdown-get-undefined-refs))
778 (refbuf (get-buffer-create (replace-regexp-in-string
779 "%BUFFER%" (buffer-name)
780 markdown-refcheck-buffer t
))))
784 (message "No undefined references found"))
785 (kill-buffer refbuf
))
786 (with-current-buffer refbuf
788 (View-exit-and-edit))
790 (insert "Following references lack definitions:")
793 (let ((button-label (format "%s" (car ref
))))
794 (if (>= emacs-major-version
22)
795 ;; Create a reference button in Emacs 22
796 (insert-text-button button-label
797 :type
'markdown-ref-button
798 'target-buffer oldbuf
)
799 ;; Insert reference as text in Emacs < 22
800 (insert button-label
)))
802 (dolist (occurency (cdr ref
))
803 (let ((line (cdr occurency
)))
804 (if (>= emacs-major-version
22)
805 ;; Create a line number button in Emacs 22
806 (insert-button (number-to-string line
)
807 :type
'goto-line-button
808 'target-buffer oldbuf
810 ;; Insert line number as text in Emacs < 22
811 (insert (number-to-string line
)))
812 (insert " "))) (delete-backward-char 1)
815 (view-buffer-other-window refbuf
)
818 ;;; Commands ==================================================================
821 "Run markdown on the current buffer and preview the output in another buffer."
823 (if (and (boundp 'transient-mark-mode
) transient-mark-mode mark-active
)
824 (shell-command-on-region (region-beginning) (region-end) markdown-command
825 "*markdown-output*" nil
)
826 (shell-command-on-region (point-min) (point-max) markdown-command
827 "*markdown-output*" nil
)))
829 (defun markdown-preview ()
830 "Run markdown on the current buffer and preview the output in a browser."
833 (browse-url-of-buffer "*markdown-output*"))
836 ;;; Miscellaneous =============================================================
838 (defun markdown-line-number-at-pos (&optional pos
)
839 "Return (narrowed) buffer line number at position POS.
840 If POS is nil, use current buffer location.
841 This is an exact copy of line-number-at-pos for use in emacs21."
842 (let ((opoint (or pos
(point))) start
)
844 (goto-char (point-min))
848 (1+ (count-lines start
(point))))))
852 ;;; Mode definition ==========================================================
854 (defun markdown-show-version ()
855 "Show the version number in the minibuffer."
857 (message "markdown-mode, version %s" markdown-mode-version
))
859 (define-derived-mode markdown-mode text-mode
"Markdown"
860 "Major mode for editing Markdown files."
862 (set (make-local-variable 'font-lock-defaults
)
863 '(markdown-mode-font-lock-keywords))
864 (set (make-local-variable 'font-lock-multiline
) t
)
865 ;; For menu support in XEmacs
866 (easy-menu-add markdown-mode-menu markdown-mode-map
))
868 ;(add-to-list 'auto-mode-alist '("\\.text$" . markdown-mode))
870 (provide 'markdown-mode
)
872 ;;; markdown-mode.el ends here