1 ;;; markdown-mode.el --- Major mode to edit Markdown files in Emacs
3 ;; Author: Jason Blevins <jrblevin@sdf.lonestar.org>
4 ;; Created: May 24, 2007
5 ;; $Id: markdown-mode.el,v 1.51 2007/12/26 15:01:37 jrblevin Exp $
6 ;; Keywords: Markdown major mode
8 ;; Copyright (C) 2007 Jason Blevins
10 ;; This program is free software; you can redistribute it and/or modify
11 ;; it under the terms of the GNU General Public License as published by
12 ;; the Free Software Foundation; either version 2, or (at your option)
15 ;; This program is distributed in the hope that it will be useful,
16 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 ;; GNU General Public License for more details.
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with this program; if not, write to the Free Software
22 ;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 ;; Emacs markdown-mode
25 ;; ===================
27 ;; [markdown-mode][] is a major mode for [GNU Emacs][] which provides syntax
28 ;; highlighting and supporting commands for editing [Markdown][] files. It
29 ;; provides keybindings and commands for inserting Markdown elements and to
30 ;; assist in calling Markdown to parse the source code or preview the document
31 ;; in a browser. It also, optionally, provides syntax highlighting for
32 ;; [wiki links](#itex) and embedded [itex](#itex) mathematical expressions.
34 ;; Markdown is a simple plain-text-based markup language for documents designed
35 ;; to be translated into HTML. It is designed to be as readable as possible.
36 ;; Markdown is also the name of the original text-to-HTML conversion tool
37 ;; written in Perl. Since its creation it has become very popular and has been
38 ;; integrated into a number of wiki and weblog packages (see the [links](#links)
41 ;; markdown-mode is free software, licensed under the [GNU GPL][].
43 ;; [markdown-mode]: http://jrblevin.freeshell.org/software/markdown-mode
44 ;; [GNU Emacs]: http://www.gnu.org/software/emacs
45 ;; [Markdown]: http://daringfireball.net/projects/markdown
46 ;; [GNU GPL]: http://www.gnu.org/copyleft/gpl.html
51 ;; The latest version is [markdown-mode 1.5][current], released on October 11,
52 ;; 2007. This [documentation](readme.txt) is also available in its original
55 ;; This release contains significant changes from the previous version,
56 ;; particularly in the area of syntax highlighting. There are still a few
57 ;; highlighting quirks, but these are mostly side effects of using Emacs'
58 ;; multi-line font lock rather than using a custom function to parse the
59 ;; document. All [previous versions][archive], such as
60 ;; [markdown-mode-1.4.el](archive/markdown-mode-1.4.el), are still available as
63 ;; This mode has only been tested on Emacs 21.4 and 22.0. Please let me know
64 ;; if there are problems on other versions. If you find any bugs, such as
65 ;; syntax highlighting issues that aren't already acknowledged in the TODO
66 ;; list, please [email](mailto:jrblevin@sdf.lonestar.org) me a test case to
69 ;; markdown-mode is also available in the Debian [emacs-goodies-el][]
70 ;; package, as of the 27.0-1 revision.
72 ;; [current]: http://jrblevin.freeshell.org/software/markdown-mode/markdown-mode.el
73 ;; [archive]: http://jrblevin.freeshell.org/software/markdown-mode/archive
74 ;; [emacs-goodies-el]: http://packages.debian.org/emacs%2Dgoodies%2Del
79 ;; Add the following lines to your `.emacs` file to associate markdown-mode with
80 ;; `.mdml` files. There doesn't seem to be a consensus on an official file
81 ;; extension so you can change this to `.text`, `.md`, `.mdt`, or whatever you
82 ;; call your markdown files.
84 ;; (autoload 'markdown-mode "markdown-mode.el"
85 ;; "Major mode for editing Markdown files" t)
86 ;; (setq auto-mode-alist
87 ;; (cons '("\\.mdml$" . markdown-mode) auto-mode-alist))
89 ;; Make sure to place this file somewhere in the load-path.
94 ;; Besides supporting the basic Markdown syntax, this mode also includes support
95 ;; for documents including embedded mathematics written [itex][] and syntax
96 ;; highlighting for `[[Wiki Links]]`. These features are designed for editing
97 ;; pages on math-enabled wikis such as [Instiki][]. One way to do this is to simply
98 ;; copy the text from your browser to Emacs, edit the page using markdown-mode,
99 ;; and then copy it back when you are finished. The other way is to use a
100 ;; plugin such as [Mozex][] for Mozilla/Firefox which allows you to call an
101 ;; external editor such as Emacs to edit textareas. You can also tell [Mozex][]
102 ;; to give the temporary file a particular extension, such as `.mdml`, so that
103 ;; markdown-mode will be loaded automatically.
105 ;; To enable syntax highlighting for itex equations and wiki links, edit
106 ;; `markdown-mode.el` and change `(defvar markdown-enable-itex nil)` to
107 ;; `(defvar markdown-enable-itex t)`.
109 ;; [itex]: http://golem.ph.utexas.edu/~distler/blog/itex2MMLcommands.html
110 ;; [Instiki]: http://golem.ph.utexas.edu/instiki
111 ;; [Mozex]: http://mozex.mozdev.org
117 ;; No configuration is necessary, although there are a few things that can be
118 ;; customized (<kbd>M-x customize-mode</kbd>).
120 ;; The element insertion keybindings are based on those of [html-helper-mode][].
121 ;; Commands are grouped by prefixes based on their function. For example,
122 ;; commands dealing with headers begin with <kdb>C-c C-t</kbd>. You can obtain
123 ;; a list of keybindings by pressing <kbd>C-c C-h</kbd> in Emacs.
125 ;; Some commands behave differently depending on whether there is an active
126 ;; selection. For example, if there is no active selection <kbd>C-c C-a l</kbd>
127 ;; will simply insert an empty `[]()` link. Otherwise, it will use the selected
128 ;; text as the link text. Most other formatting commands behave similarly.
133 ;; * Highlight inline HTML.
134 ;; * itex: Separate font locking for `\label{}` elements inside equations.
135 ;; * When inserting links (and maybe other elements), the selected should not
136 ;; remain in the kill ring.
137 ;; * Indentation and filling of list items.
138 ;; * A complete syntax table.
139 ;; * Hanging indents of list items are highlighted as preformatted text.
140 ;; * Use abbrev for quick entry of itex math mode symbols.
141 ;; * Multi-line font lock in Emacs can be unreliable. What we really need is
142 ;; a custom syntax-highlighting function.
145 ;;; User Customizable Variables ===============================================
147 ;; To enable itex/wiki syntax highlighting, change to
148 ;; (defvar markdown-enable-itex t)
149 (defvar markdown-enable-itex nil
)
152 ;;; Customizable variables ====================================================
155 (defconst markdown-mode-version
"$Revision: 1.51 $")
157 ;; A hook for users to run their own code when the mode is loaded.
158 (defvar markdown-mode-hook nil
)
161 ;;; Customizable variables ====================================================
163 (defgroup markdown nil
168 (defcustom markdown-command
"markdown"
169 "Command to run markdown."
173 (defcustom markdown-hr-length
5
174 "Length of horizonal rules."
178 (defcustom markdown-bold-underscore nil
179 "Use two underscores for bold instead of two asterisks."
183 (defcustom markdown-italic-underscore nil
184 "Use underscores for italic instead of asterisks."
189 ;;; Font lock faces ==========================================================
191 ;; Make new faces based on existing ones
193 ;;; This is not available in Emacs 21 so it has been disabled until
194 ;;; something can be built from scratch. If you are running Emacs 22 and
195 ;;; want to underline line breaks, uncomment this face and the associated
196 ;;; regular expression below.
198 ;(copy-face 'nobreak-space 'markdown-font-lock-line-break-face)
200 (copy-face 'font-lock-variable-name-face
'markdown-font-lock-italic-face
)
201 (copy-face 'font-lock-type-face
'markdown-font-lock-bold-face
)
202 (copy-face 'font-lock-builtin-face
'markdown-font-lock-inline-code-face
)
203 (copy-face 'font-lock-function-name-face
'markdown-font-lock-header-face
)
204 (copy-face 'font-lock-variable-name-face
'markdown-font-lock-list-face
)
205 (copy-face 'font-lock-comment-face
'markdown-font-lock-blockquote-face
)
206 (copy-face 'font-lock-constant-face
'markdown-font-lock-link-face
)
207 (copy-face 'font-lock-type-face
'markdown-font-lock-reference-face
)
208 (copy-face 'font-lock-string-face
'markdown-font-lock-url-face
)
209 (copy-face 'font-lock-builtin-face
'markdown-font-lock-math-face
)
211 ;; Define the extra font lock faces
212 ;(defvar markdown-font-lock-line-break-face 'markdown-font-lock-line-break-face
213 ; "Face name to use for line breaks.")
214 (defvar markdown-font-lock-italic-face
'markdown-font-lock-italic-face
215 "Face name to use for italics.")
216 (defvar markdown-font-lock-bold-face
'markdown-font-lock-bold-face
217 "Face name to use for bold.")
218 (defvar markdown-font-lock-header-face
'markdown-font-lock-header-face
219 "Face name to use for headers.")
220 (defvar markdown-font-lock-inline-code-face
'markdown-font-lock-inline-code-face
221 "Face name to use for inline code.")
222 (defvar markdown-font-lock-list-face
'markdown-font-lock-list-face
223 "Face name to use for list items.")
224 (defvar markdown-font-lock-blockquote-face
'markdown-font-lock-blockquote-face
225 "Face name to use for blockquotes and code blocks.")
226 (defvar markdown-font-lock-link-face
'markdown-font-lock-link-face
227 "Face name to use for links.")
228 (defvar markdown-font-lock-reference-face
'markdown-font-lock-reference-face
229 "Face name to use for references.")
230 (defvar markdown-font-lock-url-face
'markdown-font-lock-url-face
231 "Face name to use for URLs.")
232 (defvar markdown-font-lock-math-face
'markdown-font-lock-math-face
233 "Face name to use for itex expressions.")
236 ;;; Regular expressions =======================================================
239 (defconst regex-link-inline
"\\(!?\\[.*?\\]\\)\\(([^\\)]*)\\)"
240 "Regular expression for a [text](file) or an image link ![text](file)")
241 (defconst regex-link-reference
"\\(!?\\[.+?\\]\\)[ ]?\\(\\[.*?\\]\\)"
242 "Regular expression for a reference link [text][id]")
243 (defconst regex-reference-definition
244 "^ \\{0,3\\}\\(\\[.+?\\]\\):[ ]?\\(.*?\\)\\(\"[^\"]+?\"\\)?$"
245 "Regular expression for a link definition [id]: ...")
248 (defconst markdown-regex-latex-expression
249 "\\(^\\|[^\\]\\)\\(\\$\\($\\([^\\$]\\|\\\\.\\)*\\$\\|\\([^\\$]\\|\\\\.\\)*\\)\\$\\)"
250 "Regular expression for itex $..$ or $$..$$ math mode expressions")
252 (defconst markdown-regex-latex-display
253 "^\\\\\\[\\(.\\|\n\\)*?\\\\\\]$"
254 "Regular expression for itex \[..\] display mode expressions")
257 ;;; Font lock =================================================================
259 (defconst markdown-mode-font-lock-keywords-basic
262 ;;; Code ----------------------------------------------------------
264 ;; Double backtick style ``inline code``
265 (cons "``.+?``" 'markdown-font-lock-inline-code-face
)
266 ;; Single backtick style `inline code`
267 (cons "`.+?`" 'markdown-font-lock-inline-code-face
)
268 ;; Four-space indent style code block
269 (cons "^ .*$" 'markdown-font-lock-blockquote-face
)
271 ;;; Headers and Horizontal Rules ----------------------------------
273 ;; Equals style headers (===)
274 (cons ".*\n===+" 'markdown-font-lock-header-face
)
275 ;; Hyphen style headers (---)
276 (cons ".*\n---+" 'markdown-font-lock-header-face
)
277 ;; Hash style headers (###)
278 (cons "^#+ .*$" 'markdown-font-lock-header-face
)
279 ;; Asterisk style horizontal rules (* * *)
280 (cons "^\\*[ ]?\\*[ ]?\\*[ ]?[\\* ]*$" 'markdown-font-lock-header-face
)
281 ;; Hyphen style horizontal rules (- - -)
282 (cons "^-[ ]?-[ ]?-[--- ]*$" 'markdown-font-lock-header-face
)
284 ;;; Special cases -------------------------------------------------
286 ;; List item including bold
287 (cons "^\\s *\\* .*?[^\\\n]?\\(\\*\\*.*?[^\n\\]\\*\\*\\).*$"
288 '(1 'markdown-font-lock-bold-face
))
289 ;; List item including italics
290 (cons "^\\* .*?[^\\\n]?\\(\\*.*?[^\n\\]\\*\\).*$"
291 '(1 'markdown-font-lock-italic-face
))
293 ;;; Lists ---------------------------------------------------------
295 ;; Numbered lists (1. List item)
296 (cons "^[0-9]+\\.\\s " 'markdown-font-lock-list-face
)
297 ;; Level 1 list item (no indent) (* List item)
298 (cons "^\\(\\*\\|\\+\\|-\\) " '(1 'markdown-font-lock-list-face
))
299 ;; Level 2 list item (two or more spaces) ( * Second level list item)
300 (cons "^ [ ]*\\(\\*\\|\\+\\|-\\) " 'markdown-font-lock-list-face
)
302 ;;; Links ---------------------------------------------------------
304 (cons regex-link-inline
'(1 'markdown-font-lock-link-face t
))
305 (cons regex-link-inline
'(2 'markdown-font-lock-url-face t
))
306 (cons regex-link-reference
'(1 'markdown-font-lock-link-face t
))
307 (cons regex-link-reference
'(2 'markdown-font-lock-reference-face t
))
308 (cons regex-reference-definition
'(1 'markdown-font-lock-reference-face t
))
309 (cons regex-reference-definition
'(2 'markdown-font-lock-url-face t
))
310 (cons regex-reference-definition
'(3 'markdown-font-lock-link-face t
))
312 ;;; Bold ----------------------------------------------------------
314 ;; **Asterisk** and _underscore_ style bold
315 (cons "[^\\]\\(\\(\\*\\*\\|__\\)\\(.\\|\n\\)*?[^\\]\\2\\)"
316 '(1 'markdown-font-lock-bold-face
))
318 ;;; Italic --------------------------------------------------------
320 ;; *Asterisk* and _underscore_ style italic
321 (cons "[^\\]\\(\\(\\*\\|_\\)\\(.\\|\n\\)*?[^\\]\\2\\)"
322 '(1 'markdown-font-lock-italic-face
))
324 ;;; Blockquotes ---------------------------------------------------
326 (cons "^>.*$" 'markdown-font-lock-blockquote-face
)
328 ;;; Hard line breaks ----------------------------------------------
330 ;; Trailing whitespace (two spaces at end of line)
331 ; (cons " $" 'markdown-font-lock-line-break-face)
333 "Syntax highlighting for Markdown files.")
336 ;; Includes additional Latex/itex/Instiki font lock keywords
337 (defconst markdown-mode-font-lock-keywords-itex
341 ;;; itex expressions --------------------------------------------
343 ;; itex math mode $..$ or $$..$$
344 (cons markdown-regex-latex-expression
'(2 markdown-font-lock-math-face
))
345 ;; Display mode equations with brackets: \[ \]
346 (cons markdown-regex-latex-display
'markdown-font-lock-math-face
)
348 ;;; itex equation references ------------------------------------
350 ;; Equation reference (eq:foo)
351 (cons "(eq:\\w+)" 'markdown-font-lock-reference-face
)
352 ;; Equation reference \eqref
353 (cons "\\\\eqref{\\w+}" 'markdown-font-lock-reference-face
)
355 (cons "\\[\\[[^]]+\\]\\]" 'markdown-font-lock-link-face
))
356 markdown-mode-font-lock-keywords-basic
)
357 "Syntax highlighting for Markdown, itex, and wiki expressions.")
360 (defvar markdown-mode-font-lock-keywords
361 (if markdown-enable-itex
362 markdown-mode-font-lock-keywords-itex
363 markdown-mode-font-lock-keywords-basic
)
364 "Default highlighting expressions for Markdown mode")
367 ;;; Syntax Table ==============================================================
369 (defvar markdown-mode-syntax-table
370 (let ((markdown-mode-syntax-table (make-syntax-table)))
371 (modify-syntax-entry ?
\" "w" markdown-mode-syntax-table
)
372 markdown-mode-syntax-table
)
373 "Syntax table for markdown-mode")
376 ;;; Element Insertion =========================================================
378 (defun wrap-or-insert (s1 s2
)
379 "Insert the strings s1 and s2 around the current region or just insert them
380 if there is no region selected."
381 (if (and transient-mark-mode mark-active
)
382 (let ((a (region-beginning)) (b (region-end)))
389 (defun markdown-insert-hr ()
390 "Insert a horizonal rule."
393 (dotimes (count (- markdown-hr-length
1) hr
) ; Count to n - 1
394 (setq hr
(concat "* " hr
))) ; Build HR string
395 (setq hr
(concat hr
"*\n")) ; Add the n-th *
398 (defun markdown-insert-bold ()
399 "Make the active region bold or insert an empty bold word."
401 (if markdown-bold-underscore
402 (wrap-or-insert "__" "__")
403 (wrap-or-insert "**" "**"))
406 (defun markdown-insert-italic ()
407 "Make the active region italic or insert an empty italic word."
409 (if markdown-italic-underscore
410 (wrap-or-insert "_" "_")
411 (wrap-or-insert "*" "*"))
414 (defun markdown-insert-code ()
415 "Format the active region as inline code or insert an empty inline code
418 (wrap-or-insert "`" "`")
421 (defun markdown-insert-link ()
422 "Creates an empty link of the form [](). If there is an active region,
423 this text will be used for the link text."
425 (wrap-or-insert "[" "]")
429 (defun markdown-insert-image ()
430 "Creates an empty image of the form ![](). If there is an active region,
431 this text will be used for the alternate text for the image."
433 (wrap-or-insert "![" "]")
437 (defun markdown-insert-header-1 ()
438 "Creates a level 1 header"
440 (markdown-insert-header 1))
442 (defun markdown-insert-header-2 ()
443 "Creates a level 2 header"
445 (markdown-insert-header 2))
447 (defun markdown-insert-header-3 ()
448 "Creates a level 3 header"
450 (markdown-insert-header 3))
452 (defun markdown-insert-header-4 ()
453 "Creates a level 4 header"
455 (markdown-insert-header 4))
457 (defun markdown-insert-header-5 ()
458 "Creates a level 5 header"
460 (markdown-insert-header 5))
462 (defun markdown-insert-header (n)
463 "Creates a level n header. If there is an active region, it is used as the
466 (unless n
; Test to see if n is defined
467 (setq n
1)) ; Default to level 1 header
469 (dotimes (count n hdr
)
470 (setq hdr
(concat "#" hdr
))) ; Build a ### header string
471 (setq hdrl
(concat hdr
" "))
472 (setq hdrr
(concat " " hdr
))
473 (wrap-or-insert hdrl hdrr
))
474 (backward-char (+ 1 n
)))
476 (defun markdown-insert-title ()
477 "Use the active region to create an \"equals\" style title or insert
478 a blank title and move the cursor to the required position in order to
481 (if (and transient-mark-mode mark-active
)
482 (let ((a (region-beginning))
487 (dotimes (count len hdr
)
488 (setq hdr
(concat "=" hdr
))) ; Build a === title underline
490 (insert "\n" hdr
"\n"))
491 (insert "\n==========\n")
494 (defun markdown-insert-section ()
495 "Use the active region to create a dashed style section or insert
496 a blank section and move the cursor to the required position in order to
499 (if (and transient-mark-mode mark-active
)
500 (let ((a (region-beginning))
505 (dotimes (count len hdr
)
506 (setq hdr
(concat "-" hdr
))) ; Build a --- section underline
508 (insert "\n" hdr
"\n"))
509 (insert "\n----------\n")
512 (defun markdown-insert-blockquote ()
513 "Start a blank blockquote section unless there is an active region, in
514 which case it is turned into a blockquote region."
516 (if (and (boundp 'transient-mark-mode
) transient-mark-mode mark-active
)
521 ;;; Keymap ====================================================================
523 (defvar markdown-mode-map
524 (let ((markdown-mode-map (make-keymap)))
526 (define-key markdown-mode-map
"\C-c\C-al" 'markdown-insert-link
)
527 (define-key markdown-mode-map
"\C-c\C-ii" 'markdown-insert-image
)
528 (define-key markdown-mode-map
"\C-c\C-t1" 'markdown-insert-header-1
)
529 (define-key markdown-mode-map
"\C-c\C-t2" 'markdown-insert-header-2
)
530 (define-key markdown-mode-map
"\C-c\C-t3" 'markdown-insert-header-3
)
531 (define-key markdown-mode-map
"\C-c\C-t4" 'markdown-insert-header-4
)
532 (define-key markdown-mode-map
"\C-c\C-t5" 'markdown-insert-header-5
)
533 (define-key markdown-mode-map
"\C-c\C-pb" 'markdown-insert-bold
)
534 (define-key markdown-mode-map
"\C-c\C-ss" 'markdown-insert-bold
)
535 (define-key markdown-mode-map
"\C-c\C-pi" 'markdown-insert-italic
)
536 (define-key markdown-mode-map
"\C-c\C-se" 'markdown-insert-italic
)
537 (define-key markdown-mode-map
"\C-c\C-pf" 'markdown-insert-code
)
538 (define-key markdown-mode-map
"\C-c\C-sc" 'markdown-insert-code
)
539 (define-key markdown-mode-map
"\C-c\C-sb" 'markdown-insert-blockquote
)
540 (define-key markdown-mode-map
"\C-c-" 'markdown-insert-hr
)
541 (define-key markdown-mode-map
"\C-c\C-tt" 'markdown-insert-title
)
542 (define-key markdown-mode-map
"\C-c\C-ts" 'markdown-insert-section
)
543 ;; Markdown functions
544 (define-key markdown-mode-map
"\C-c\C-cm" 'markdown
)
545 (define-key markdown-mode-map
"\C-c\C-cp" 'markdown-preview
)
547 "Keymap for Markdown major mode")
550 ;;; Markdown ==================================================================
553 "Run markdown on the current buffer and preview the output in another buffer."
555 (if (and (boundp 'transient-mark-mode
) transient-mark-mode mark-active
)
556 (shell-command-on-region region-beginning region-end markdown-command
557 "*markdown-output*" nil
)
558 (shell-command-on-region (point-min) (point-max) markdown-command
559 "*markdown-output*" nil
)))
561 (defun markdown-preview ()
562 "Run markdown on the current buffer and preview the output in a browser."
565 (browse-url-of-buffer "*markdown-output*"))
568 ;;; Utilities =================================================================
570 (defun markdown-show-version ()
571 "Show the version number in the minibuffer."
573 (message "markdown-mode, version %s" markdown-mode-version
))
575 (defun blockquote-region ()
576 "Blockquote an entire region."
578 (if (and (boundp 'transient-mark-mode
) transient-mark-mode mark-active
)
579 (perform-replace "^" "> " nil
1 nil nil nil
(region-beginning) (region-end))))
582 ;;; Mode definition ==========================================================
584 (define-derived-mode markdown-mode fundamental-mode
"Markdown"
585 "Major mode for editing Markdown files."
587 (set (make-local-variable 'font-lock-defaults
)
588 '(markdown-mode-font-lock-keywords))
589 (set (make-local-variable 'font-lock-multiline
) t
))
591 ;(add-to-list 'auto-mode-alist '("\\.mdml$" . markdown-mode))
593 (provide 'markdown-mode
)
595 ;;; markdown-mode.el ends here