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.6, released on June 4. 2008:
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/20080604-001.png
45 ;; [release notes]: http://jblevins.org/projects/markdown-mode/rev-1-6
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
144 ;; Markdown mode supports outline-minor-mode as well as org-mode-style
145 ;; visibility cycling for atx- or hash-style headers. There are two
146 ;; types of visibility cycling: Pressing `S-TAB` cycles globally between
147 ;; the table of contents view (headers only), outline view (top-level
148 ;; headers only), and the full document view. Pressing `TAB` while the
149 ;; point is at a header will cycle through levels of visibility for the
150 ;; subtree: completely folded, visiable children, and fully visible.
151 ;; Note that mixing hash and underline style headers will give undesired
156 ;; Besides supporting the basic Markdown syntax, markdown-mode also
157 ;; includes syntax highlighting for `[[Wiki Links]]` by default.
159 ;; [SmartyPants][] support is possible by customizing `markdown-command`.
160 ;; If you install `SmartyPants.pl` at, say, `/usr/local/bin/smartypants`,
161 ;; then you can set `markdown-command` to `"markdown | smartypants"`.
162 ;; You can do this either by using `M-x customize-group markdown`
163 ;; or by placing the following in your `.emacs` file:
165 ;; (defun markdown-custom ()
166 ;; "markdown-mode-hook"
167 ;; (setq markdown-command "markdown | smartypants"))
168 ;; (add-hook 'markdown-mode-hook '(lambda() (markdown-custom)))
170 ;; Experimental syntax highlighting for mathematical expressions written
171 ;; in LaTeX (only expressions denoted by `$..$`, `$$..$$`, or `\[..\]`)
172 ;; can be enabled by editing `markdown-mode.el` and changing `(defvar
173 ;; markdown-enable-itex nil)` to `(defvar markdown-enable-itex t)`.
175 ;; [SmartyPants]: http://daringfireball.net/projects/smartypants/
179 ;; * Cyril Brulebois <cyril.brulebois@enst-bretagne.fr> for Debian packaging.
180 ;; * Conal Elliott <conal@conal.net> for a font-lock regexp patch.
181 ;; * Edward O'Connor <hober0@gmail.com> for a font-lock regexp fix.
182 ;; * Greg Bognar <greg_bognar@hms.harvard.edu> for menus and a patch.
183 ;; * Daniel Burrows <dburrows@debian.org> for filing Debian bug #456592.
184 ;; * Peter S. Galbraith <psg@debian.org> for maintaining emacs-goodies-el.
185 ;; * Dmitry Dzhus <mail@sphinx.net.ru> for reference checking functions.
189 ;; Markdown mode is developed and tested primarily using GNU Emacs 22
190 ;; although compatibility with GNU Emacs 21 is also a priority.
192 ;; Presently Markdown mode does not attempt to distinguish between
193 ;; multiple indentation levels and preformatted text (four or more
194 ;; leading spaces). I am not aware of a way to handle this using
195 ;; Emacs's regexp-based font-lock facilities. Implementing a more
196 ;; robust approach to syntax highlighting is a high-priority item for
199 ;; If you find any bugs, such as syntax highlighting issues, please
200 ;; construct a test case and email me at <jrblevin@sdf.lonestar.org>.
201 ;; Comments and patches are welcome!
205 ;; markdown-mode was written and is maintained by Jason Blevins. The
206 ;; first revision, 1.1, was released on May 24, 2007.
216 ;;; User Customizable Variables ===============================================
218 ;; To enable LaTeX/itex syntax highlighting, change to
219 ;; (defvar markdown-enable-itex t)
220 (defvar markdown-enable-itex nil
)
223 ;;; Customizable variables ====================================================
226 (defconst markdown-mode-version
"1.7-dev")
228 ;; A hook for users to run their own code when the mode is loaded.
229 (defvar markdown-mode-hook nil
)
232 ;;; Customizable variables ====================================================
234 (defgroup markdown nil
235 "Major mode for editing text files in Markdown format."
238 :link
'(url-link "http://jblevins.org/projects/markdown-mode/"))
240 (defcustom markdown-command
"markdown"
241 "Command to run markdown."
245 (defcustom markdown-hr-length
5
246 "Length of horizonal rules."
250 (defcustom markdown-bold-underscore nil
251 "Use two underscores for bold instead of two asterisks."
255 (defcustom markdown-italic-underscore nil
256 "Use underscores for italic instead of asterisks."
261 ;;; Font lock =================================================================
265 (defgroup markdown-faces nil
266 "Faces used in Markdown Mode"
270 (defvar markdown-italic-face
'markdown-italic-face
)
271 (defface markdown-italic-face
'((t :inherit font-lock-variable-name-face
))
273 :group
'markdown-faces
)
275 (defvar markdown-bold-face
'markdown-bold-face
)
276 (defface markdown-bold-face
'((t :inherit font-lock-type-face
))
278 :group
'markdown-faces
)
280 (defvar markdown-header-face-1
'markdown-header-face-1
)
281 (defface markdown-header-face-1
'((t :inherit markdown-header-face
))
283 :group
'markdown-faces
)
285 (defvar markdown-header-face-2
'markdown-header-face-2
)
286 (defface markdown-header-face-2
'((t :inherit markdown-header-face
))
288 :group
'markdown-faces
)
290 (defvar markdown-header-face-3
'markdown-header-face-3
)
291 (defface markdown-header-face-3
'((t :inherit markdown-header-face
))
293 :group
'markdown-faces
)
295 (defvar markdown-header-face-4
'markdown-header-face-4
)
296 (defface markdown-header-face-4
'((t :inherit markdown-header-face
))
298 :group
'markdown-faces
)
300 (defvar markdown-inline-code-face
'markdown-inline-code-face
)
301 (defface markdown-inline-code-face
'((t inherit font-lock-builtin-face
))
303 :group
'markdown-faces
)
305 (defvar markdown-list-face
'markdown-list-face
)
306 (defface markdown-list-face
'((t :inherit font-lock-variable-name-face
))
308 :group
'markdown-faces
)
310 (defvar markdown-blockquote-face
'markdown-blockquote-face
)
311 (defface markdown-blockquote-face
'((t :inherit font-lock-comment-face
))
312 "Blockquote sections and preformatted text."
313 :group
'markdown-faces
)
315 (defvar markdown-link-face
'markdown-link-face
)
316 (defface markdown-link-face
'((t :inherit font-lock-constant-face
))
318 :group
'markdown-faces
)
320 (defvar markdown-reference-face
'markdown-reference-face
)
321 (defface markdown-reference-face
'((t :inherit font-lock-type-face
))
323 :group
'markdown-faces
)
325 (defvar markdown-url-face
'markdown-url-face
)
326 (defface markdown-url-face
'((t :inherit font-lock-string-face
))
328 :group
'markdown-faces
)
330 (defvar markdown-math-face
'markdown-math-face
)
331 (defface markdown-math-face
'((t :inherit font-lock-builtin-face
))
333 :group
'markdown-faces
)
335 (defconst markdown-regex-link-inline
336 "\\(!?\\[[^]]*?\\]\\)\\(([^\\)]*)\\)"
337 "Regular expression for a [text](file) or an image link ![text](file).")
339 (defconst markdown-regex-link-reference
340 "\\(!?\\[[^]]+?\\]\\)[ ]?\\(\\[[^]]*?\\]\\)"
341 "Regular expression for a reference link [text][id].")
343 (defconst markdown-regex-reference-definition
344 "^ \\{0,3\\}\\(\\[.+?\\]\\):\\s *\\(.*?\\)\\s *\\( \"[^\"]*\"$\\|$\\)"
345 "Regular expression for a link definition [id]: ...")
347 (defconst markdown-regex-header-1-atx
348 "^\\(# \\)\\(.*?\\)\\($\\| #+$\\)"
349 "Regular expression for level 1 atx-style (hash mark) headers.")
351 (defconst markdown-regex-header-2-atx
352 "^\\(## \\)\\(.*?\\)\\($\\| #+$\\)"
353 "Regular expression for level 2 atx-style (hash mark) headers.")
355 (defconst markdown-regex-header-3-atx
356 "^\\(### \\)\\(.*?\\)\\($\\| #+$\\)"
357 "Regular expression for level 3 atx-style (hash mark) headers.")
359 (defconst markdown-regex-header-4-atx
360 "^\\(#### \\)\\(.*?\\)\\($\\| #+$\\)"
361 "Regular expression for level 4 atx-style (hash mark) headers.")
363 (defconst markdown-regex-header-1-setext
364 "^\\(.*\\)\n\\(===+\\)$"
365 "Regular expression for level 1 setext-style (underline) headers.")
367 (defconst markdown-regex-header-2-setext
368 "^\\(.*\\)\n\\(---+\\)$"
369 "Regular expression for level 2 setext-style (underline) headers.")
371 (defconst markdown-regex-hr
372 "^\\(\\*[ ]?\\*[ ]?\\*[ ]?[\\* ]*\\|-[ ]?-[ ]?-[--- ]*\\)$"
373 "Regular expression for matching Markdown horizontal rules.")
375 (defconst markdown-regex-code
376 "\\(^\\|[^\\]\\)\\(\\(`\\{1,2\\}\\)\\([^ \\]\\|[^ ].*?[^ \\]\\)\\3\\)"
377 "Regular expression for matching inline code fragments.")
379 (defconst markdown-regex-pre
381 "Regular expression for matching preformatted text sections.")
383 (defconst markdown-regex-list
384 "^[ \t]*\\([0-9]+\\.\\|[\\*\\+-]\\) "
385 "Regular expression for matching list markers.")
387 (defconst markdown-regex-bold
388 "\\(^\\|[^\\]\\)\\(\\([*_]\\{2\\}\\)\\(.\\|\n\\)*?[^\\ ]\\3\\)"
389 "Regular expression for matching bold text.")
391 (defconst markdown-regex-italic
392 "\\(^\\|[^\\]\\)\\(\\([*_]\\)\\([^ \\]\\3\\|[^ ]\\(.\\|\n\\)*?[^\\ ]\\3\\)\\)"
393 "Regular expression for matching italic text.")
395 (defconst markdown-regex-blockquote
397 "Regular expression for matching blockquote lines.")
399 (defconst markdown-regex-line-break
401 "Regular expression for matching line breaks.")
403 (defconst markdown-regex-wiki-link
405 "Regular expression for matching wiki links.")
407 (defconst markdown-regex-uri
408 "<\\(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\\)://[^>]*>"
409 "Regular expression for matching inline URIs.")
411 (defconst markdown-regex-email
412 "<\\(\\sw\\|\\s_\\|\\s.\\)+@\\(\\sw\\|\\s_\\|\\s.\\)+>"
413 "Regular expression for matching inline email addresses.")
415 (defconst markdown-regex-latex-expression
416 "\\(^\\|[^\\]\\)\\(\\$\\($\\([^\\$]\\|\\\\.\\)*\\$\\|\\([^\\$]\\|\\\\.\\)*\\)\\$\\)"
417 "Regular expression for itex $..$ or $$..$$ math mode expressions.")
419 (defconst markdown-regex-latex-display
420 "^\\\\\\[\\(.\\|\n\\)*?\\\\\\]$"
421 "Regular expression for itex \[..\] display mode expressions.")
423 (defvar markdown-mode-font-lock-keywords-basic
425 (cons markdown-regex-code
'(2 markdown-inline-code-face
))
426 (cons markdown-regex-pre
'markdown-blockquote-face
)
427 (cons markdown-regex-blockquote
'markdown-blockquote-face
)
428 (cons markdown-regex-header-1-setext
'markdown-header-face-1
)
429 (cons markdown-regex-header-2-setext
'markdown-header-face-2
)
430 (cons markdown-regex-header-1-atx
'markdown-header-face-1
)
431 (cons markdown-regex-header-2-atx
'markdown-header-face-2
)
432 (cons markdown-regex-header-3-atx
'markdown-header-face-3
)
433 (cons markdown-regex-header-4-atx
'markdown-header-face-4
)
434 (cons markdown-regex-hr
'markdown-header-face
)
435 (cons markdown-regex-list
'markdown-list-face
)
436 (cons markdown-regex-link-inline
437 '((1 markdown-link-face t
)
438 (2 markdown-url-face t
)))
439 (cons markdown-regex-link-reference
440 '((1 markdown-link-face t
)
441 (2 markdown-reference-face t
)))
442 (cons markdown-regex-reference-definition
443 '((1 markdown-reference-face t
)
444 (2 markdown-url-face t
)
445 (3 markdown-link-face t
)))
446 (cons markdown-regex-wiki-link
'markdown-link-face
)
447 (cons markdown-regex-bold
'(2 markdown-bold-face
))
448 (cons markdown-regex-italic
'(2 markdown-italic-face
))
449 (cons markdown-regex-uri
'markdown-link-face
)
450 (cons markdown-regex-email
'markdown-link-face
)
452 "Syntax highlighting for Markdown files.")
455 ;; Includes additional Latex/itex/Instiki font lock keywords
456 (defconst markdown-mode-font-lock-keywords-itex
459 ;; itex math mode $..$ or $$..$$
460 (cons markdown-regex-latex-expression
'(2 markdown-math-face
))
461 ;; Display mode equations with brackets: \[ \]
462 (cons markdown-regex-latex-display
'markdown-math-face
)
463 ;; Equation reference (eq:foo)
464 (cons "(eq:\\w+)" 'markdown-reference-face
)
465 ;; Equation reference \eqref
466 (cons "\\\\eqref{\\w+}" 'markdown-reference-face
))
467 markdown-mode-font-lock-keywords-basic
)
468 "Syntax highlighting for Markdown, itex, and wiki expressions.")
471 (defvar markdown-mode-font-lock-keywords
472 (if markdown-enable-itex
473 markdown-mode-font-lock-keywords-itex
474 markdown-mode-font-lock-keywords-basic
)
475 "Default highlighting expressions for Markdown mode.")
479 ;;; Syntax Table ==============================================================
481 (defvar markdown-mode-syntax-table
482 (let ((markdown-mode-syntax-table (make-syntax-table)))
483 (modify-syntax-entry ?
\" "w" markdown-mode-syntax-table
)
484 markdown-mode-syntax-table
)
485 "Syntax table for `markdown-mode'.")
489 ;;; Element Insertion =========================================================
491 (defun markdown-wrap-or-insert (s1 s2
)
492 "Insert the strings S1 and S2.
493 If Transient Mark mode is on and a region is active, wrap the strings S1
494 and S2 around the region."
495 (if (and transient-mark-mode mark-active
)
496 (let ((a (region-beginning)) (b (region-end)))
499 (goto-char (+ b
(length s1
)))
503 (defun markdown-insert-hr ()
504 "Insert a horizonal rule."
507 (dotimes (count (- markdown-hr-length
1) hr
) ; Count to n - 1
508 (setq hr
(concat "* " hr
))) ; Build HR string
509 (setq hr
(concat hr
"*\n")) ; Add the n-th *
512 (defun markdown-insert-bold ()
513 "Insert markup for a bold word or phrase.
514 If Transient Mark mode is on and a region is active, it is made bold."
516 (if markdown-bold-underscore
517 (markdown-wrap-or-insert "__" "__")
518 (markdown-wrap-or-insert "**" "**"))
521 (defun markdown-insert-italic ()
522 "Insert markup for an italic word or phrase.
523 If Transient Mark mode is on and a region is active, it is made italic."
525 (if markdown-italic-underscore
526 (markdown-wrap-or-insert "_" "_")
527 (markdown-wrap-or-insert "*" "*"))
530 (defun markdown-insert-code ()
531 "Insert markup for an inline code fragment.
532 If Transient Mark mode is on and a region is active, it is marked
535 (markdown-wrap-or-insert "`" "`")
538 (defun markdown-insert-link ()
539 "Insert an inline link of the form []().
540 If Transient Mark mode is on and a region is active, it is used
543 (markdown-wrap-or-insert "[" "]")
547 (defun markdown-insert-wiki-link ()
548 "Insert a wiki link of the form [[WikiLink]].
549 If Transient Mark mode is on and a region is active, it is used
552 (markdown-wrap-or-insert "[[" "]]")
555 (defun markdown-insert-image ()
556 "Insert an inline image tag of the form ![]().
557 If Transient Mark mode is on and a region is active, it is used
558 as the alt text of the image."
560 (markdown-wrap-or-insert "![" "]")
564 (defun markdown-insert-header-1 ()
565 "Insert a first level atx-style (hash mark) header.
566 If Transient Mark mode is on and a region is active, it is used
569 (markdown-insert-header 1))
571 (defun markdown-insert-header-2 ()
572 "Insert a second level atx-style (hash mark) header.
573 If Transient Mark mode is on and a region is active, it is used
576 (markdown-insert-header 2))
578 (defun markdown-insert-header-3 ()
579 "Insert a third level atx-style (hash mark) header.
580 If Transient Mark mode is on and a region is active, it is used
583 (markdown-insert-header 3))
585 (defun markdown-insert-header-4 ()
586 "Insert a fourth level atx-style (hash mark) header.
587 If Transient Mark mode is on and a region is active, it is used
590 (markdown-insert-header 4))
592 (defun markdown-insert-header-5 ()
593 "Insert a fifth level atx-style (hash mark) header.
594 If Transient Mark mode is on and a region is active, it is used
597 (markdown-insert-header 5))
599 (defun markdown-insert-header (n)
600 "Insert an atx-style (hash mark) header.
601 With no prefix argument, insert a level-1 header. With prefix N,
602 insert a level-N header. If Transient Mark mode is on and the
603 region is active, it is used as the header text."
605 (unless n
; Test to see if n is defined
606 (setq n
1)) ; Default to level 1 header
608 (dotimes (count n hdr
)
609 (setq hdr
(concat "#" hdr
))) ; Build a hash mark header string
610 (setq hdrl
(concat hdr
" "))
611 (setq hdrr
(concat " " hdr
))
612 (markdown-wrap-or-insert hdrl hdrr
))
613 (backward-char (+ 1 n
)))
615 (defun markdown-insert-title ()
616 "Insert a setext-style (underline) first level header.
617 If Transient Mark mode is on and a region is active, it is used
620 (if (and transient-mark-mode mark-active
)
621 (let ((a (region-beginning))
626 (dotimes (count len hdr
)
627 (setq hdr
(concat "=" hdr
))) ; Build a === title underline
629 (insert "\n" hdr
"\n"))
630 (insert "\n==========\n")
633 (defun markdown-insert-section ()
634 "Insert a setext-style (underline) second level header.
635 If Transient Mark mode is on and a region is active, it is used
638 (if (and transient-mark-mode mark-active
)
639 (let ((a (region-beginning))
644 (dotimes (count len hdr
)
645 (setq hdr
(concat "-" hdr
))) ; Build a --- section underline
647 (insert "\n" hdr
"\n"))
648 (insert "\n----------\n")
651 (defun markdown-insert-blockquote ()
652 "Start a blockquote section (or blockquote the region).
653 If Transient Mark mode is on and a region is active, it is used as
654 the blockquote text."
656 (if (and (boundp 'transient-mark-mode
) transient-mark-mode mark-active
)
657 (markdown-blockquote-region (region-beginning) (region-end))
660 (defun markdown-block-region (beg end prefix
)
661 "Format the region using a block prefix.
662 The characters PREFIX will appear at the beginning of each line.
663 Arguments BEG and END specify the beginning and end of the
668 ; Ensure that there is a leading blank line
670 (while (not (looking-back "\n\n" 2))
672 (setq endpos
(+ 1 endpos
)))
673 ; Insert blockquote characters
674 (move-to-left-margin)
675 (while (< (point-at-bol) endpos
)
677 (setq endpos
(+ (length prefix
) endpos
))
679 ; Move back before any blank lines at the end
681 (while (looking-back "\n" 1)
683 ; Ensure one blank line at the end
684 (while (not (looking-at "\n\n"))
688 (defun markdown-blockquote-region (beg end
)
689 "Blockquote the region.
690 Arguments BEG and END specify the beginning and end of the region."
692 (markdown-block-region beg end
"> "))
694 (defun markdown-insert-pre ()
695 "Start a preformatted section (or apply to the region).
696 If Transient Mark mode is on and a region is active, it is marked
697 as preformatted text."
699 (if (and (boundp 'transient-mark-mode
) transient-mark-mode mark-active
)
700 (markdown-pre-region (region-beginning) (region-end))
703 (defun markdown-pre-region (beg end
)
704 "Format the region as preformatted text.
705 Arguments BEG and END specify the beginning and end of the region."
707 (markdown-block-region beg end
" "))
712 ;;; Keymap ====================================================================
714 (defvar markdown-mode-map
715 (let ((markdown-mode-map (make-keymap)))
717 (define-key markdown-mode-map
"\C-c\C-al" 'markdown-insert-link
)
718 (define-key markdown-mode-map
"\C-c\C-aw" 'markdown-insert-wiki-link
)
719 (define-key markdown-mode-map
"\C-c\C-ii" 'markdown-insert-image
)
720 (define-key markdown-mode-map
"\C-c\C-t1" 'markdown-insert-header-1
)
721 (define-key markdown-mode-map
"\C-c\C-t2" 'markdown-insert-header-2
)
722 (define-key markdown-mode-map
"\C-c\C-t3" 'markdown-insert-header-3
)
723 (define-key markdown-mode-map
"\C-c\C-t4" 'markdown-insert-header-4
)
724 (define-key markdown-mode-map
"\C-c\C-t5" 'markdown-insert-header-5
)
725 (define-key markdown-mode-map
"\C-c\C-pb" 'markdown-insert-bold
)
726 (define-key markdown-mode-map
"\C-c\C-ss" 'markdown-insert-bold
)
727 (define-key markdown-mode-map
"\C-c\C-pi" 'markdown-insert-italic
)
728 (define-key markdown-mode-map
"\C-c\C-se" 'markdown-insert-italic
)
729 (define-key markdown-mode-map
"\C-c\C-pf" 'markdown-insert-code
)
730 (define-key markdown-mode-map
"\C-c\C-sc" 'markdown-insert-code
)
731 (define-key markdown-mode-map
"\C-c\C-sb" 'markdown-insert-blockquote
)
732 (define-key markdown-mode-map
"\C-c\C-s\C-b" 'markdown-blockquote-region
)
733 (define-key markdown-mode-map
"\C-c\C-sp" 'markdown-insert-pre
)
734 (define-key markdown-mode-map
"\C-c\C-s\C-p" 'markdown-pre-region
)
735 (define-key markdown-mode-map
"\C-c-" 'markdown-insert-hr
)
736 (define-key markdown-mode-map
"\C-c\C-tt" 'markdown-insert-title
)
737 (define-key markdown-mode-map
"\C-c\C-ts" 'markdown-insert-section
)
738 ;; Visibility cycling
739 (define-key markdown-mode-map
(kbd "<tab>") 'markdown-cycle
)
740 (define-key markdown-mode-map
(kbd "<S-iso-lefttab>") 'markdown-shifttab
)
741 ;; Markdown functions
742 (define-key markdown-mode-map
"\C-c\C-cm" 'markdown
)
743 (define-key markdown-mode-map
"\C-c\C-cp" 'markdown-preview
)
745 (define-key markdown-mode-map
"\C-c\C-cc" 'markdown-check-refs
)
747 "Keymap for Markdown major mode.")
749 ;;; Menu ==================================================================
751 (easy-menu-define markdown-mode-menu markdown-mode-map
752 "Menu for Markdown mode"
755 ["Cycle visibility" markdown-cycle
(outline-on-heading-p)]
756 ["Cycle global visibility" markdown-shifttab
])
759 ["Preview" markdown-preview
]
762 ["Insert Title" markdown-insert-title
]
763 ["Insert Section" markdown-insert-section
])
765 ["First level" markdown-insert-header-1
]
766 ["Second level" markdown-insert-header-2
]
767 ["Third level" markdown-insert-header-3
]
768 ["Fourth level" markdown-insert-header-4
]
769 ["Fifth level" markdown-insert-header-5
])
771 ["Bold" markdown-insert-bold
]
772 ["Italic" markdown-insert-italic
]
773 ["Blockquote" markdown-insert-blockquote
]
774 ["Preformatted" markdown-insert-pre
]
775 ["Code" markdown-insert-code
]
777 ["Insert inline link" markdown-insert-link
]
778 ["Insert image" markdown-insert-image
]
779 ["Insert horizontal rule" markdown-insert-hr
]
781 ["Check references" markdown-check-refs
]
783 ["Version" markdown-show-version
]
788 ;;; References ================================================================
790 ;;; Undefined reference checking code by Dmitry Dzhus <mail@sphinx.net.ru>.
792 (defconst markdown-refcheck-buffer
793 "*Undefined references for %BUFFER%*"
794 "Pattern for name of buffer for listing undefined references.
795 The string %BUFFER% will be replaced by the corresponding
796 `markdown-mode' buffer name.")
798 (defun markdown-has-reference-definition (reference)
799 "Find out whether Markdown REFERENCE is defined.
801 REFERENCE should include the square brackets, like [this]."
802 (let ((reference (downcase reference
)))
804 (goto-char (point-min))
806 (while (re-search-forward markdown-regex-reference-definition nil t
)
807 (when (string= reference
(downcase (match-string-no-properties 1)))
808 (throw 'found t
)))))))
810 (defun markdown-get-undefined-refs ()
811 "Return a list of undefined Markdown references.
813 Result is an alist of pairs (reference . occurencies), where
814 occurencies is itself another alist of pairs (label .
817 For example, an alist corresponding to [Nice editor][Emacs] at line 12,
818 \[GNU Emacs][Emacs] at line 45 and [manual][elisp] at line 127 is
819 \((\"[emacs]\" (\"[Nice editor]\" . 12) (\"[GNU Emacs]\" . 45)) (\"[elisp]\" (\"[manual]\" . 127)))."
822 (goto-char (point-min))
824 (re-search-forward markdown-regex-link-reference nil t
)
825 (let* ((label (match-string-no-properties 1))
826 (reference (match-string-no-properties 2))
827 (target (downcase (if (string= reference
"[]") label reference
))))
828 (unless (markdown-has-reference-definition target
)
829 (let ((entry (assoc target missing
)))
831 (add-to-list 'missing
(cons target
832 (list (cons label
(markdown-line-number-at-pos)))) t
)
834 (append (cdr entry
) (list (cons label
(markdown-line-number-at-pos))))))))))
837 (defun markdown-add-missing-ref-definition (ref buffer
&optional recheck
)
838 "Add blank REF definition to the end of BUFFER.
840 REF is a Markdown reference in square brackets, like \"[lisp-history]\".
842 When RECHECK is non-nil, BUFFER gets rechecked for undefined
843 references so that REF disappears from the list of those links."
844 (with-current-buffer buffer
845 (when (not (eq major-mode
'markdown-mode
))
846 (error "Not available in current mdoe"))
847 (goto-char (point-max))
848 (indent-new-comment-line)
849 (insert (concat ref
": ")))
850 (switch-to-buffer-other-window buffer
)
851 (goto-char (point-max))
853 (markdown-check-refs t
)))
855 ;; Button which adds an empty Markdown reference definition to the end
856 ;; of buffer specified as its 'target-buffer property. Reference name
858 (when (>= emacs-major-version
22)
859 (define-button-type 'markdown-ref-button
860 'help-echo
"Push to create an empty reference definition"
863 (markdown-add-missing-ref-definition
864 (button-label b
) (button-get b
'target-buffer
) t
))))
866 ;; Button jumping to line in buffer specified as its 'target-buffer
867 ;; property. Line number is button's 'line property.
868 (when (>= emacs-major-version
22)
869 (define-button-type 'goto-line-button
870 'help-echo
"Push to go to this line"
873 (message (button-get b
'buffer
))
874 (switch-to-buffer-other-window (button-get b
'target-buffer
))
875 (goto-line (button-get b
'target-line
)))))
877 (defun markdown-check-refs (&optional silent
)
878 "Show all undefined Markdown references in current `markdown-mode' buffer.
880 If SILENT is non-nil, do not message anything when no undefined
883 Links which have empty reference definitions are considered to be
886 (when (not (eq major-mode
'markdown-mode
))
887 (error "Not available in current mode"))
888 (let ((oldbuf (current-buffer))
889 (refs (markdown-get-undefined-refs))
890 (refbuf (get-buffer-create (replace-regexp-in-string
891 "%BUFFER%" (buffer-name)
892 markdown-refcheck-buffer t
))))
896 (message "No undefined references found"))
897 (kill-buffer refbuf
))
898 (with-current-buffer refbuf
900 (View-exit-and-edit))
902 (insert "Following references lack definitions:")
905 (let ((button-label (format "%s" (car ref
))))
906 (if (>= emacs-major-version
22)
907 ;; Create a reference button in Emacs 22
908 (insert-text-button button-label
909 :type
'markdown-ref-button
910 'target-buffer oldbuf
)
911 ;; Insert reference as text in Emacs < 22
912 (insert button-label
)))
914 (dolist (occurency (cdr ref
))
915 (let ((line (cdr occurency
)))
916 (if (>= emacs-major-version
22)
917 ;; Create a line number button in Emacs 22
918 (insert-button (number-to-string line
)
919 :type
'goto-line-button
920 'target-buffer oldbuf
922 ;; Insert line number as text in Emacs < 22
923 (insert (number-to-string line
)))
924 (insert " "))) (delete-backward-char 1)
927 (view-buffer-other-window refbuf
)
931 ;;; Outline ===================================================================
933 ;; The following visibility cycling code was taken from org-mode
934 ;; by Carsten Dominik and adapted for markdown-mode.
936 (defvar markdown-cycle-global-status
1)
937 (defvar markdown-cycle-subtree-status nil
)
939 ;; Based on org-end-of-subtree from org.el
940 (defun markdown-end-of-subtree (&optional invisible-OK
)
941 "Move to the end of the current subtree.
942 Only visible heading lines are considered, unless INVISIBLE-OK is
944 (outline-back-to-heading invisible-OK
)
946 (level (funcall outline-level
)))
947 (while (and (not (eobp))
948 (or first
(> (funcall outline-level
) level
)))
950 (outline-next-heading))
951 (if (memq (preceding-char) '(?
\n ?\^M
))
953 ;; Go to end of line before heading
955 (if (memq (preceding-char) '(?
\n ?\^M
))
956 ;; leave blank line before heading
957 (forward-char -
1)))))
960 ;; Based on org-cycle from org.el.
961 (defun markdown-cycle (&optional arg
)
962 "Visibility cycling for Markdown mode.
963 If ARG is t, perform global visibility cycling. If the point is
964 at an atx-style header, cycle visibility of the corresponding
965 subtree. Otherwise, insert a tab using `indent-relative'."
968 ((eq arg t
) ;; Global cycling
970 ((and (eq last-command this-command
)
971 (eq markdown-cycle-global-status
2))
972 ;; Move from overview to contents
975 (setq markdown-cycle-global-status
3))
977 ((and (eq last-command this-command
)
978 (eq markdown-cycle-global-status
3))
979 ;; Move from contents to all
982 (setq markdown-cycle-global-status
1))
985 ;; Defaults to overview
988 (setq markdown-cycle-global-status
2))))
990 ((save-excursion (beginning-of-line 1) (looking-at outline-regexp
))
991 ;; At a heading: rotate between three different views
992 (outline-back-to-heading)
993 (let ((goal-column 0) eoh eol eos
)
994 ;; Determine boundaries
996 (outline-back-to-heading)
998 (beginning-of-line 2)
999 (while (and (not (eobp)) ;; this is like `next-line'
1000 (get-char-property (1- (point)) 'invisible
))
1001 (beginning-of-line 2)) (setq eol
(point)))
1002 (outline-end-of-heading) (setq eoh
(point))
1003 (markdown-end-of-subtree t
)
1004 (skip-chars-forward " \t\n")
1005 (beginning-of-line 1) ; in case this is an item
1006 (setq eos
(1- (point))))
1007 ;; Find out what to do next and set `this-command'
1010 ;; Nothing is hidden behind this heading
1011 (message "EMPTY ENTRY")
1012 (setq markdown-cycle-subtree-status nil
))
1014 ;; Entire subtree is hidden in one line: open it
1017 (message "CHILDREN")
1018 (setq markdown-cycle-subtree-status
'children
))
1019 ((and (eq last-command this-command
)
1020 (eq markdown-cycle-subtree-status
'children
))
1021 ;; We just showed the children, now show everything.
1024 (setq markdown-cycle-subtree-status
'subtree
))
1026 ;; Default action: hide the subtree.
1029 (setq markdown-cycle-subtree-status
'folded
)))))
1033 (indent-relative))))
1035 ;; Based on org-shifttab from org.el.
1036 (defun markdown-shifttab ()
1037 "Global visibility cycling.
1038 Calls `markdown-cycle' with argument t."
1042 ;;; Commands ==================================================================
1045 "Run markdown on the current buffer and preview the output in another buffer."
1047 (if (and (boundp 'transient-mark-mode
) transient-mark-mode mark-active
)
1048 (shell-command-on-region (region-beginning) (region-end) markdown-command
1049 "*markdown-output*" nil
)
1050 (shell-command-on-region (point-min) (point-max) markdown-command
1051 "*markdown-output*" nil
)))
1053 (defun markdown-preview ()
1054 "Run markdown on the current buffer and preview the output in a browser."
1057 (browse-url-of-buffer "*markdown-output*"))
1060 ;;; Miscellaneous =============================================================
1062 (defun markdown-line-number-at-pos (&optional pos
)
1063 "Return (narrowed) buffer line number at position POS.
1064 If POS is nil, use current buffer location.
1065 This is an exact copy of `line-number-at-pos' for use in emacs21."
1066 (let ((opoint (or pos
(point))) start
)
1068 (goto-char (point-min))
1069 (setq start
(point))
1072 (1+ (count-lines start
(point))))))
1076 ;;; Mode definition ==========================================================
1078 (defun markdown-show-version ()
1079 "Show the version number in the minibuffer."
1081 (message "markdown-mode, version %s" markdown-mode-version
))
1083 (define-derived-mode markdown-mode text-mode
"Markdown"
1084 "Major mode for editing Markdown files."
1086 (set (make-local-variable 'font-lock-defaults
)
1087 '(markdown-mode-font-lock-keywords))
1088 (set (make-local-variable 'font-lock-multiline
) t
)
1089 ;; For menu support in XEmacs
1090 (easy-menu-add markdown-mode-menu markdown-mode-map
)
1091 ;; Make filling work with lists
1092 (set (make-local-variable 'paragraph-start
)
1093 "\f\\|[ \t]*$\\|^[ \t]*[*+-] \\|^[ \t*][0-9]+\\. ")
1095 (make-local-variable 'outline-regexp
)
1096 (setq outline-regexp
"#+")
1097 ;; Cause use of ellipses for invisible text.
1098 (add-to-invisibility-spec '(outline . t
)))
1100 ;(add-to-list 'auto-mode-alist '("\\.text$" . markdown-mode))
1102 (provide 'markdown-mode
)
1104 ;;; markdown-mode.el ends here