Begin 1.9 development version
[markdown-mode.git] / markdown-mode.el
blob966f067752daf0e68585615ee1d8e13261da552d
1 ;;; markdown-mode.el --- Emacs Major mode for Markdown-formatted text files
3 ;; Copyright (C) 2007-2011 Jason R. Blevins <jrblevin@sdf.org>
4 ;; Copyright (C) 2007, 2009 Edward O'Connor <ted@oconnor.cx>
5 ;; Copyright (C) 2007 Conal Elliott <conal@conal.net>
6 ;; Copyright (C) 2008 Greg Bognar <greg_bognar@hms.harvard.edu>
7 ;; Copyright (C) 2008 Dmitry Dzhus <mail@sphinx.net.ru>
8 ;; Copyright (C) 2008 Bryan Kyle <bryan.kyle@gmail.com>
9 ;; Copyright (C) 2008 Ben Voui <intrigeri@boum.org>
10 ;; Copyright (C) 2009 Ankit Solanki <ankit.solanki@gmail.com>
11 ;; Copyright (C) 2009 Hilko Bengen <bengen@debian.org>
12 ;; Copyright (C) 2009 Peter Williams <pezra@barelyenough.org>
13 ;; Copyright (C) 2010 George Ogata <george.ogata@gmail.com>
14 ;; Copyright (C) 2011 Eric Merritt <ericbmerritt@gmail.com>
15 ;; Copyright (C) 2011 Philippe Ivaldi <pivaldi@sfr.fr>
16 ;; Copyright (C) 2011 Jeremiah Dodds <jeremiah.dodds@gmail.com>
18 ;; Author: Jason R. Blevins <jrblevin@sdf.org>
19 ;; Maintainer: Jason R. Blevins <jrblevin@sdf.org>
20 ;; Created: May 24, 2007
21 ;; Version: 1.9-dev
22 ;; Keywords: Markdown, GitHub Flavored Markdown, itex
23 ;; URL: http://jblevins.org/projects/markdown-mode/
25 ;; This file is not part of GNU Emacs.
27 ;; This program is free software; you can redistribute it and/or modify
28 ;; it under the terms of the GNU General Public License as published by
29 ;; the Free Software Foundation; either version 2, or (at your option)
30 ;; any later version.
32 ;; This program is distributed in the hope that it will be useful,
33 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
34 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
35 ;; GNU General Public License for more details.
37 ;; You should have received a copy of the GNU General Public License
38 ;; along with this program; if not, write to the Free Software
39 ;; Foundation, Inc., 51 Franklin Street, Fifth Floor,
40 ;; Boston, MA 02110-1301, USA.
42 ;;; Commentary:
44 ;; markdown-mode is a major mode for editing [Markdown][]-formatted
45 ;; text files in GNU Emacs. markdown-mode is free software, licensed
46 ;; under the GNU GPL.
48 ;; [Markdown]: http://daringfireball.net/projects/markdown/
50 ;; The latest stable version is markdown-mode 1.8, released on August 12, 2011:
52 ;; * [markdown-mode.el][]
53 ;; * [Screenshot][]
54 ;; * [Release notes][]
56 ;; [markdown-mode.el]: http://jblevins.org/projects/markdown-mode/markdown-mode.el
57 ;; [screenshot]: http://jblevins.org/projects/markdown-mode/screenshots/20110812-001.png
58 ;; [release notes]: http://jblevins.org/projects/markdown-mode/rev-1-8
60 ;; markdown-mode is also available in several package managers, including:
62 ;; * Debian and Ubuntu Linux: [emacs-goodies-el][]
63 ;; * RedHat and Fedora Linux: [emacs-goodies][]
64 ;; * OpenBSD: [textproc/markdown-mode][]
65 ;; * Arch Linux (AUR): [emacs-markdown-mode-git][]
67 ;; [emacs-goodies-el]: http://packages.debian.org/emacs-goodies-el
68 ;; [emacs-goodies]: https://admin.fedoraproject.org/pkgdb/acls/name/emacs-goodies
69 ;; [textproc/markdown-mode]: http://pkgsrc.se/textproc/markdown-mode
70 ;; [emacs-markdown-mode-git]: http://aur.archlinux.org/packages.php?ID=30389
72 ;; The latest development version can be downloaded directly
73 ;; ([markdown-mode.el][devel.el]) or it can be obtained from the
74 ;; (browsable and clonable) Git repository at
75 ;; <http://jblevins.org/git/markdown-mode.git>. The entire repository,
76 ;; including the full project history, can be cloned via the Git protocol
77 ;; by running
79 ;; git clone git://jblevins.org/git/markdown-mode.git
81 ;; [devel.el]: http://jblevins.org/git/markdown-mode.git/plain/markdown-mode.el
83 ;;; Dependencies:
85 ;; markdown-mode requires easymenu, a standard package since GNU Emacs
86 ;; 19 and XEmacs 19, which provides a uniform interface for creating
87 ;; menus in GNU Emacs and XEmacs.
89 ;;; Installation:
91 ;; Make sure to place `markdown-mode.el` somewhere in the load-path and add
92 ;; the following lines to your `.emacs` file to associate markdown-mode
93 ;; with `.text` files:
95 ;; (autoload 'markdown-mode "markdown-mode.el"
96 ;; "Major mode for editing Markdown files" t)
97 ;; (setq auto-mode-alist
98 ;; (cons '("\\.text" . markdown-mode) auto-mode-alist))
100 ;; There is no consensus on an official file extension so change `.text` to
101 ;; `.mdwn`, `.md`, `.mdt`, or whatever you call your markdown files.
103 ;;; Customization:
105 ;; Although no configuration is *necessary* there are a few things
106 ;; that can be customized. The `M-x customize-mode` command
107 ;; provides an interface to all of the possible customizations:
109 ;; * `markdown-command' - the command used to run Markdown (default:
110 ;; `markdown'). This variable may be customized to pass
111 ;; command-line options to your Markdown processor of choice, but
112 ;; this command must accept input from `stdin`. If it does not, a
113 ;; simple wrapper script can be used to write `stdin` to a file
114 ;; and then pass that file to your Markdown interpreter. Ideally,
115 ;; this command will produce an XHTML fragment around which
116 ;; markdown-mode will wrap a header and footer (which can be
117 ;; further customized). However, it attempts to detect whether
118 ;; the command produces standalone XHTML output (via
119 ;; `markdown-xhtml-standalone-regexp'), in which case no header
120 ;; and footer content will be added.
122 ;; * `markdown-command-needs-filename' - set to non-nil if
123 ;; `markdown-command' does not accept input from stdin (default: nil).
124 ;; Instead, it will be passed a filename as the final command-line
125 ;; option. As a result, you will only be able to run Markdown
126 ;; from buffers which are visiting a file.
128 ;; * `markdown-hr-string' - string to use when inserting horizontal
129 ;; rules (default: `* * * * *').
131 ;; * `markdown-bold-underscore' - set to a non-nil value to use two
132 ;; underscores for bold instead of two asterisks (default: `nil').
134 ;; * `markdown-italic-underscore' - set to a non-nil value to use
135 ;; underscores for italic instead of asterisks (default: `nil').
137 ;; * `markdown-indent-function' - the function to use for automatic
138 ;; indentation (default: `markdown-indent-line').
140 ;; * `markdown-indent-on-enter' - set to a non-nil value to
141 ;; automatically indent new lines when the enter key is pressed
142 ;; (default: `t')
144 ;; * `markdown-follow-wiki-link-on-enter' - set to a non-nil value
145 ;; to automatically open a linked document in a new buffer if the
146 ;; cursor is an wiki link
147 ;; (default: `t')
149 ;; * `markdown-uri-types' - a list of protocols for URIs that
150 ;; `markdown-mode' should highlight.
152 ;; * `markdown-enable-math' - syntax highlighting for
153 ;; LaTeX fragments (default: `nil').
155 ;; * `markdown-css-path' - CSS file to link to in XHTML output.
157 ;; * `markdown-xhtml-header-content' - additional content to include
158 ;; in the XHTML <head> block.
160 ;; * `markdown-xhtml-standalone-regexp' - a regular expression which
161 ;; indicates whether the output of `markdown-command' is standalone
162 ;; XHTML (default: `^\\(\<\?xml\\|\<!DOCTYPE\\|\<html\\)`). If
163 ;; this is not matched, we assume this output is a fragment and add
164 ;; our own header and footer.
166 ;; Additionally, the faces used for syntax highlighting can be modified to
167 ;; your liking by issuing `M-x customize-group RET markdown-faces`
168 ;; or by using the "Markdown Faces" link at the bottom of the mode
169 ;; customization screen.
171 ;;; Usage:
173 ;; Keybindings are grouped by prefixes based on their function. For
174 ;; example, commands dealing with headers begin with `C-c C-t`. The
175 ;; primary commands in each group will are described below. You can
176 ;; obtain a list of all keybindings by pressing `C-c C-h`.
178 ;; * Anchors: `C-c C-a`
180 ;; `C-c C-a l` inserts inline links of the form `[text](url)`. If
181 ;; there is an active region, text in the region is used for the
182 ;; link text. `C-c C-a w` acts similarly for wiki links of the
183 ;; form `[[WikiLink]]`.
185 ;; * Commands: `C-c C-c`
187 ;; `C-c C-c m` will run Markdown on the current buffer and preview
188 ;; the output in another buffer while `C-c C-c p` runs Markdown on
189 ;; the current buffer and previews the output in a browser.
190 ;; `C-c C-c e` will run Markdown on the current buffer and save
191 ;; the result in the file `basename.html`, where `basename` is the
192 ;; name of the Markdown file with the extension removed. **This
193 ;; file will be overwritten without notice.** Press `C-c C-c v`
194 ;; to view the exported file in a browser.
196 ;; `C-c C-c c` will check for undefined references. If there are
197 ;; any, a small buffer will open with a list of undefined
198 ;; references and the line numbers on which they appear. In Emacs
199 ;; 22 and greater, selecting a reference from this list and
200 ;; pressing `RET` will insert an empty reference definition at the
201 ;; end of the buffer. Similarly, selecting the line number will
202 ;; jump to the corresponding line.
204 ;; * Images: `C-c C-i`
206 ;; `C-c C-i i` inserts an image, using the active region (if any)
207 ;; as the alt text.
209 ;; * Physical styles: `C-c C-p`
211 ;; These commands all act on text in the active region, if any,
212 ;; and insert empty markup fragments otherwise. `C-c C-p b` makes
213 ;; the selected text bold, `C-c C-p f` formats the region as
214 ;; fixed-width text, and `C-c C-p i` is used for italic text.
216 ;; * Logical styles: `C-c C-s`
218 ;; These commands all act on text in the active region, if any,
219 ;; and insert empty markup fragments otherwise. Logical styles
220 ;; include blockquote (`C-c C-s b`), preformatted (`C-c C-s p`),
221 ;; code (`C-c C-s c`), emphasis (`C-c C-s e`), and strong (`C-c
222 ;; C-s s`).
224 ;; * Headers: `C-c C-t`
226 ;; All header commands use text in the active region, if any, as
227 ;; the header text. To insert an atx or hash style level-n
228 ;; header, press `C-c C-t n` where n is between 1 and 6. For a
229 ;; top-level setext or underline style header press `C-c C-t t`
230 ;; (mnemonic: title) and for a second-level underline-style header
231 ;; press `C-c C-t s` (mnemonic: section).
233 ;; * Other elements:
235 ;; `C-c -` inserts a horizontal rule.
237 ;; * Wiki-Link Navigation:
239 ;; Use `M-p` and `M-n` to quickly jump to the previous and next
240 ;; wiki links, respectively.
242 ;; * Outline Navigation:
244 ;; Navigation between headings is possible using `outline-mode'.
245 ;; Use `C-M-n` and `C-M-p` to move between the next and previous
246 ;; visible headings. Similarly, `C-M-f` and `C-M-b` move to the
247 ;; next and previous visible headings at the same level as the one
248 ;; at the point. Finally, `C-M-u` will move up to a lower-level
249 ;; (more inclusive) visible heading.
251 ;; Many of the commands described above behave differently depending on
252 ;; whether Transient Mark mode is enabled or not. When it makes sense,
253 ;; if Transient Mark mode is on and a region is active, the command
254 ;; applies to the text in the region (e.g., `C-c C-p b` makes the region
255 ;; bold). For users who prefer to work outside of Transient Mark mode,
256 ;; in Emacs 22 it can be enabled temporarily by pressing `C-SPC C-SPC`.
258 ;; When applicable, commands that specifically act on the region even
259 ;; outside of Transient Mark mode have the same keybinding as the with
260 ;; the exception of an additional `C-` prefix. For example,
261 ;; `markdown-insert-blockquote' is bound to `C-c C-s b` and only acts on
262 ;; the region in Transient Mark mode while `markdown-blockquote-region'
263 ;; is bound to `C-c C-s C-b` and always applies to the region (when
264 ;; nonempty).
266 ;; markdown-mode attempts to be flexible in how it handles
267 ;; indentation. When you press `TAB` repeatedly, the point will cycle
268 ;; through several possible indentation levels corresponding to things
269 ;; you might have in mind when you press `RET` at the end of a line or
270 ;; `TAB`. For example, you may want to start a new list item,
271 ;; continue a list item with hanging indentation, indent for a nested
272 ;; pre block, and so on.
274 ;; markdown-mode supports outline-minor-mode as well as org-mode-style
275 ;; visibility cycling for atx- or hash-style headers. There are two
276 ;; types of visibility cycling: Pressing `S-TAB` cycles globally between
277 ;; the table of contents view (headers only), outline view (top-level
278 ;; headers only), and the full document view. Pressing `TAB` while the
279 ;; point is at a header will cycle through levels of visibility for the
280 ;; subtree: completely folded, visible children, and fully visible.
281 ;; Note that mixing hash and underline style headers will give undesired
282 ;; results.
284 ;;; Extensions:
286 ;; Besides supporting the basic Markdown syntax, markdown-mode also
287 ;; includes syntax highlighting for `[[Wiki Links]]` by default. Wiki
288 ;; links may be followed automatically by hitting the enter key when
289 ;; your curser is on a wiki link or by hitting `C-c C-f`. The
290 ;; autofollowing on enter key may be controlled with the
291 ;; `markdown-follow-wiki-link-on-enter' customization. Use `M-p` and
292 ;; `M-n` to quickly jump to the previous and next wiki links,
293 ;; respectively.
295 ;; [SmartyPants][] support is possible by customizing `markdown-command'.
296 ;; If you install `SmartyPants.pl` at, say, `/usr/local/bin/smartypants`,
297 ;; then you can set `markdown-command' to `"markdown | smartypants"`.
298 ;; You can do this either by using `M-x customize-group markdown`
299 ;; or by placing the following in your `.emacs` file:
301 ;; (defun markdown-custom ()
302 ;; "markdown-mode-hook"
303 ;; (setq markdown-command "markdown | smartypants"))
304 ;; (add-hook 'markdown-mode-hook '(lambda() (markdown-custom)))
306 ;; [SmartyPants]: http://daringfireball.net/projects/smartypants/
308 ;; Experimental syntax highlighting for mathematical expressions written
309 ;; in LaTeX (only expressions denoted by `$..$`, `$$..$$`, or `\[..\]`)
310 ;; can be enabled by setting `markdown-enable-math' to a non-nil value,
311 ;; either via customize or by placing `(setq markdown-enable-itex t)`
312 ;; in `.emacs`, and restarting Emacs.
314 ;; A [GitHub Flavored Markdown](http://github.github.com/github-flavored-markdown/)
315 ;; mode, `gfm-mode', is also available. The GitHub implementation of
316 ;; differs slightly from standard Markdown. Most importantly, newlines are
317 ;; significant and trigger hard line breaks. As such, `gfm-mode' turns off
318 ;; `auto-fill-mode' and turns on `longlines-mode'.
320 ;;; Acknowledgments:
322 ;; markdown-mode has benefited greatly from the efforts of the
323 ;; following people:
325 ;; * Cyril Brulebois <cyril.brulebois@enst-bretagne.fr> for Debian packaging.
326 ;; * Conal Elliott <conal@conal.net> for a font-lock regexp patch.
327 ;; * Edward O'Connor <hober0@gmail.com> for a font-lock regexp fix and
328 ;; GitHub Flavored Markdown mode (`gfm-mode').
329 ;; * Greg Bognar <greg_bognar@hms.harvard.edu> for menus and running
330 ;; `markdown' with an active region.
331 ;; * Daniel Burrows <dburrows@debian.org> for filing Debian bug #456592.
332 ;; * Peter S. Galbraith <psg@debian.org> for maintaining emacs-goodies-el.
333 ;; * Dmitry Dzhus <mail@sphinx.net.ru> for reference checking functions.
334 ;; * Bryan Kyle <bryan.kyle@gmail.com> for indentation code.
335 ;; * Ben Voui <intrigeri@boum.org> for font-lock face customizations.
336 ;; * Ankit Solanki <ankit.solanki@gmail.com> for longlines.el
337 ;; compatibility and custom CSS.
338 ;; * Hilko Bengen <bengen@debian.org> for proper XHTML output.
339 ;; * Jose A. Ortega Ruiz <jao@gnu.org> for Emacs 23 fixes.
340 ;; * Alec Resnick <alec@sproutward.org> for bug reports.
341 ;; * Joost Kremers <j.kremers@em.uni-frankfurt.de> for bug reports
342 ;; regarding indentation.
343 ;; * Peter Williams <pezra@barelyenough.org> for fill-paragraph
344 ;; enhancements.
345 ;; * George Ogata <george.ogata@gmail.com> for fixing several
346 ;; byte-compilation warnings.
347 ;; * Eric Merritt <ericbmerritt@gmail.com> for wiki link features.
348 ;; * Philippe Ivaldi <pivaldi@sfr.fr> for XHTML preview
349 ;; customizations and XHTML export.
350 ;; * Jeremiah Dodds <jeremiah.dodds@gmail.com> for supporting
351 ;; Markdown processors which do not accept input from stdin.
353 ;;; Bugs:
355 ;; Although markdown-mode is developed and tested primarily using
356 ;; GNU Emacs 24, compatibility with earlier Emacsen is also a
357 ;; priority.
359 ;; If you find any bugs in markdown-mode, please construct a test case
360 ;; or a patch and email me at <jrblevin@sdf.org>.
362 ;;; History:
364 ;; markdown-mode was written and is maintained by Jason Blevins. The
365 ;; first version was released on May 24, 2007.
367 ;; * 2007-05-24: Version 1.1
368 ;; * 2007-05-25: Version 1.2
369 ;; * 2007-06-05: [Version 1.3][]
370 ;; * 2007-06-29: Version 1.4
371 ;; * 2008-05-24: [Version 1.5][]
372 ;; * 2008-06-04: [Version 1.6][]
373 ;; * 2009-10-01: [Version 1.7][]
374 ;; * 2011-08-12: [Version 1.8][]
376 ;; [Version 1.3]: http://jblevins.org/projects/markdown-mode/rev-1-3
377 ;; [Version 1.5]: http://jblevins.org/projects/markdown-mode/rev-1-5
378 ;; [Version 1.6]: http://jblevins.org/projects/markdown-mode/rev-1-6
379 ;; [Version 1.7]: http://jblevins.org/projects/markdown-mode/rev-1-7
380 ;; [Version 1.8]: http://jblevins.org/projects/markdown-mode/rev-1-8
383 ;;; Code:
385 (require 'easymenu)
386 (require 'outline)
388 ;;; Constants =================================================================
390 (defconst markdown-mode-version "1.9-dev"
391 "Markdown mode version number.")
393 (defconst markdown-output-buffer-name "*markdown-output*"
394 "Name of temporary buffer for markdown command output.")
396 ;;; Customizable variables ====================================================
398 (defvar markdown-mode-hook nil
399 "Hook runs when Markdown mode is loaded.")
401 (defgroup markdown nil
402 "Major mode for editing text files in Markdown format."
403 :prefix "markdown-"
404 :group 'wp
405 :link '(url-link "http://jblevins.org/projects/markdown-mode/"))
407 (defcustom markdown-command "markdown"
408 "Command to run markdown."
409 :group 'markdown
410 :type 'string)
412 (defcustom markdown-command-needs-filename nil
413 "Set to non-nil if `markdown-command' does not accept input from stdin.
414 Instead, it will be passed a filename as the final command-line
415 option. As a result, you will only be able to run Markdown from
416 buffers which are visiting a file."
417 :group 'markdown
418 :type 'boolean)
420 (defcustom markdown-hr-string "* * * * *"
421 "String to use for horizonal rules."
422 :group 'markdown
423 :type 'string)
425 (defcustom markdown-bold-underscore nil
426 "Use two underscores for bold instead of two asterisks."
427 :group 'markdown
428 :type 'boolean)
430 (defcustom markdown-italic-underscore nil
431 "Use underscores for italic instead of asterisks."
432 :group 'markdown
433 :type 'boolean)
435 (defcustom markdown-indent-function 'markdown-indent-line
436 "Function to use to indent."
437 :group 'markdown
438 :type 'function)
440 (defcustom markdown-indent-on-enter t
441 "Automatically indent new lines when enter key is pressed."
442 :group 'markdown
443 :type 'boolean)
445 (defcustom markdown-follow-wiki-link-on-enter t
446 "Follow wiki link at point (if any) when the enter key is pressed."
447 :group 'markdown
448 :type 'boolean)
450 (defcustom markdown-uri-types
451 '("acap" "cid" "data" "dav" "fax" "file" "ftp" "gopher" "http" "https"
452 "imap" "ldap" "mailto" "mid" "modem" "news" "nfs" "nntp" "pop" "prospero"
453 "rtsp" "service" "sip" "tel" "telnet" "tip" "urn" "vemmi" "wais")
454 "Link types for syntax highlighting of URIs."
455 :group 'markdown
456 :type 'list)
458 (defcustom markdown-enable-math nil
459 "Syntax highlighting for inline LaTeX expressions.
460 This will not take effect until Emacs is restarted."
461 :group 'markdown
462 :type 'boolean)
464 (defcustom markdown-css-path ""
465 "URL of CSS file to link to in the output XHTML."
466 :group 'markdown
467 :type 'string)
469 (defcustom markdown-xhtml-header-content ""
470 "Additional content to include in the XHTML <head> block."
471 :group 'markdown
472 :type 'string)
474 (defcustom markdown-xhtml-standalone-regexp
475 "^\\(\<\?xml\\|\<!DOCTYPE\\|\<html\\)"
476 "Regexp indicating whether `markdown-command' output is standalone XHTML."
477 :group 'markdown
478 :type 'regexp)
480 ;;; Font lock =================================================================
482 (require 'font-lock)
484 (defvar markdown-italic-face 'markdown-italic-face
485 "Face name to use for italic text.")
487 (defvar markdown-bold-face 'markdown-bold-face
488 "Face name to use for bold text.")
490 (defvar markdown-header-face 'markdown-header-face
491 "Face name to use as a base for headers.")
493 (defvar markdown-header-face-1 'markdown-header-face-1
494 "Face name to use for level-1 headers.")
496 (defvar markdown-header-face-2 'markdown-header-face-2
497 "Face name to use for level-2 headers.")
499 (defvar markdown-header-face-3 'markdown-header-face-3
500 "Face name to use for level-3 headers.")
502 (defvar markdown-header-face-4 'markdown-header-face-4
503 "Face name to use for level-4 headers.")
505 (defvar markdown-header-face-5 'markdown-header-face-5
506 "Face name to use for level-5 headers.")
508 (defvar markdown-header-face-6 'markdown-header-face-6
509 "Face name to use for level-6 headers.")
511 (defvar markdown-inline-code-face 'markdown-inline-code-face
512 "Face name to use for inline code.")
514 (defvar markdown-list-face 'markdown-list-face
515 "Face name to use for list markers.")
517 (defvar markdown-blockquote-face 'markdown-blockquote-face
518 "Face name to use for blockquote.")
520 (defvar markdown-pre-face 'markdown-pre-face
521 "Face name to use for preformatted text.")
523 (defvar markdown-link-face 'markdown-link-face
524 "Face name to use for links.")
526 (defvar markdown-missing-link-face 'markdown-missing-link-face
527 "Face name to use for links where the linked file does not exist.")
529 (defvar markdown-reference-face 'markdown-reference-face
530 "Face name to use for reference.")
532 (defvar markdown-url-face 'markdown-url-face
533 "Face name to use for URLs.")
535 (defvar markdown-link-title-face 'markdown-link-title-face
536 "Face name to use for reference link titles.")
538 (defvar markdown-comment-face 'markdown-comment-face
539 "Face name to use for HTML comments.")
541 (defvar markdown-math-face 'markdown-math-face
542 "Face name to use for LaTeX expressions.")
544 (defgroup markdown-faces nil
545 "Faces used in Markdown Mode"
546 :group 'markdown
547 :group 'faces)
549 (defface markdown-italic-face
550 '((t :inherit font-lock-variable-name-face :italic t))
551 "Face for italic text."
552 :group 'markdown-faces)
554 (defface markdown-bold-face
555 '((t :inherit font-lock-variable-name-face :bold t))
556 "Face for bold text."
557 :group 'markdown-faces)
559 (defface markdown-header-face
560 '((t :inherit font-lock-function-name-face :weight bold))
561 "Base face for headers."
562 :group 'markdown-faces)
564 (defface markdown-header-face-1
565 '((t :inherit markdown-header-face))
566 "Face for level-1 headers."
567 :group 'markdown-faces)
569 (defface markdown-header-face-2
570 '((t :inherit markdown-header-face))
571 "Face for level-2 headers."
572 :group 'markdown-faces)
574 (defface markdown-header-face-3
575 '((t :inherit markdown-header-face))
576 "Face for level-3 headers."
577 :group 'markdown-faces)
579 (defface markdown-header-face-4
580 '((t :inherit markdown-header-face))
581 "Face for level-4 headers."
582 :group 'markdown-faces)
584 (defface markdown-header-face-5
585 '((t :inherit markdown-header-face))
586 "Face for level-5 headers."
587 :group 'markdown-faces)
589 (defface markdown-header-face-6
590 '((t :inherit markdown-header-face))
591 "Face for level-6 headers."
592 :group 'markdown-faces)
594 (defface markdown-inline-code-face
595 '((t :inherit font-lock-constant-face))
596 "Face for inline code."
597 :group 'markdown-faces)
599 (defface markdown-list-face
600 '((t :inherit font-lock-builtin-face))
601 "Face for list item markers."
602 :group 'markdown-faces)
604 (defface markdown-blockquote-face
605 '((t :inherit font-lock-doc-face))
606 "Face for blockquote sections."
607 :group 'markdown-faces)
609 (defface markdown-pre-face
610 '((t :inherit font-lock-constant-face))
611 "Face for preformatted text."
612 :group 'markdown-faces)
614 (defface markdown-link-face
615 '((t :inherit font-lock-keyword-face))
616 "Face for links."
617 :group 'markdown-faces)
619 (defface markdown-missing-link-face
620 '((t :inherit font-lock-warning-face))
621 "Face for missing links."
622 :group 'markdown-faces)
624 (defface markdown-reference-face
625 '((t :inherit font-lock-type-face))
626 "Face for link references."
627 :group 'markdown-faces)
629 (defface markdown-url-face
630 '((t :inherit font-lock-string-face))
631 "Face for URLs."
632 :group 'markdown-faces)
634 (defface markdown-link-title-face
635 '((t :inherit font-lock-comment-face))
636 "Face for reference link titles."
637 :group 'markdown-faces)
639 (defface markdown-comment-face
640 '((t :inherit font-lock-comment-face))
641 "Face for HTML comments."
642 :group 'markdown-faces)
644 (defface markdown-math-face
645 '((t :inherit font-lock-string-face))
646 "Face for LaTeX expressions."
647 :group 'markdown-faces)
649 (defconst markdown-regex-link-inline
650 "\\(!?\\[[^]]*?\\]\\)\\(([^\\)]*)\\)"
651 "Regular expression for a [text](file) or an image link ![text](file).")
653 (defconst markdown-regex-link-reference
654 "\\(!?\\[[^]]+?\\]\\)[ ]?\\(\\[[^]]*?\\]\\)"
655 "Regular expression for a reference link [text][id].")
657 (defconst markdown-regex-reference-definition
658 "^ \\{0,3\\}\\(\\[.+?\\]\\):\\s *\\(.*?\\)\\s *\\( \"[^\"]*\"$\\|$\\)"
659 "Regular expression for a link definition [id]: ...")
661 (defconst markdown-regex-header-1-atx
662 "^\\(# \\)\\(.*?\\)\\($\\| #+$\\)"
663 "Regular expression for level 1 atx-style (hash mark) headers.")
665 (defconst markdown-regex-header-2-atx
666 "^\\(## \\)\\(.*?\\)\\($\\| #+$\\)"
667 "Regular expression for level 2 atx-style (hash mark) headers.")
669 (defconst markdown-regex-header-3-atx
670 "^\\(### \\)\\(.*?\\)\\($\\| #+$\\)"
671 "Regular expression for level 3 atx-style (hash mark) headers.")
673 (defconst markdown-regex-header-4-atx
674 "^\\(#### \\)\\(.*?\\)\\($\\| #+$\\)"
675 "Regular expression for level 4 atx-style (hash mark) headers.")
677 (defconst markdown-regex-header-5-atx
678 "^\\(##### \\)\\(.*?\\)\\($\\| #+$\\)"
679 "Regular expression for level 5 atx-style (hash mark) headers.")
681 (defconst markdown-regex-header-6-atx
682 "^\\(###### \\)\\(.*?\\)\\($\\| #+$\\)"
683 "Regular expression for level 6 atx-style (hash mark) headers.")
685 (defconst markdown-regex-header-1-setext
686 "^\\(.*\\)\n\\(===+\\)$"
687 "Regular expression for level 1 setext-style (underline) headers.")
689 (defconst markdown-regex-header-2-setext
690 "^\\(.*\\)\n\\(---+\\)$"
691 "Regular expression for level 2 setext-style (underline) headers.")
693 (defconst markdown-regex-hr
694 "^\\(\\*[ ]?\\*[ ]?\\*[ ]?[\\* ]*\\|-[ ]?-[ ]?-[--- ]*\\)$"
695 "Regular expression for matching Markdown horizontal rules.")
697 (defconst markdown-regex-code
698 "\\(^\\|[^\\]\\)\\(\\(`\\{1,2\\}\\)\\([^ \\]\\|[^ ]\\(.\\|\n[^\n]\\)*?[^ \\]\\)\\3\\)"
699 "Regular expression for matching inline code fragments.")
701 (defconst markdown-regex-pre
702 "^\\( \\|\t\\).*$"
703 "Regular expression for matching preformatted text sections.")
705 (defconst markdown-regex-list
706 "^[ \t]*\\([0-9]+\\.\\|[\\*\\+-]\\) "
707 "Regular expression for matching list markers.")
709 (defconst markdown-regex-bold
710 "\\(^\\|[^\\]\\)\\(\\([*_]\\{2\\}\\)\\(.\\|\n[^\n]\\)*?[^\\ ]\\3\\)"
711 "Regular expression for matching bold text.")
713 (defconst markdown-regex-italic
714 "\\(^\\|[^\\]\\)\\(\\([*_]\\)\\([^ \\]\\3\\|[^ ]\\(.\\|\n[^\n]\\)*?[^\\ ]\\3\\)\\)"
715 "Regular expression for matching italic text.")
717 (defconst markdown-regex-blockquote
718 "^>.*$"
719 "Regular expression for matching blockquote lines.")
721 (defconst markdown-regex-line-break
722 " $"
723 "Regular expression for matching line breaks.")
725 (defconst markdown-regex-wiki-link
726 "\\[\\[\\([^]]+\\)\\]\\]"
727 "Regular expression for matching wiki links.")
729 (defconst markdown-regex-uri
730 (concat
731 "\\(" (mapconcat 'identity markdown-uri-types "\\|")
732 "\\):[^]\t\n\r<>,;() ]+")
733 "Regular expression for matching inline URIs.")
735 (defconst markdown-regex-angle-uri
736 (concat
737 "\\(<\\)\\("
738 (mapconcat 'identity markdown-uri-types "\\|")
739 "\\):[^]\t\n\r<>,;()]+\\(>\\)")
740 "Regular expression for matching inline URIs in angle brackets.")
742 (defconst markdown-regex-email
743 "<\\(\\sw\\|\\s_\\|\\s.\\)+@\\(\\sw\\|\\s_\\|\\s.\\)+>"
744 "Regular expression for matching inline email addresses.")
746 (defconst markdown-regex-latex-expression
747 "\\(^\\|[^\\]\\)\\(\\$\\($\\([^\\$]\\|\\\\.\\)*\\$\\|\\([^\\$]\\|\\\\.\\)*\\)\\$\\)"
748 "Regular expression for itex $..$ or $$..$$ math mode expressions.")
750 (defconst markdown-regex-latex-display
751 "^\\\\\\[\\(.\\|\n\\)*?\\\\\\]$"
752 "Regular expression for itex \[..\] display mode expressions.")
754 (defconst markdown-regex-list-indent
755 "^\\(\\s *\\)\\([0-9]+\\.\\|[\\*\\+-]\\)\\(\\s +\\)"
756 "Regular expression for matching indentation of list items.")
758 (defvar markdown-mode-font-lock-keywords-basic
759 (list
760 '(markdown-match-pre-blocks 0 markdown-pre-face t t)
761 (cons markdown-regex-blockquote 'markdown-blockquote-face)
762 (cons markdown-regex-header-1-setext 'markdown-header-face-1)
763 (cons markdown-regex-header-2-setext 'markdown-header-face-2)
764 (cons markdown-regex-header-1-atx 'markdown-header-face-1)
765 (cons markdown-regex-header-2-atx 'markdown-header-face-2)
766 (cons markdown-regex-header-3-atx 'markdown-header-face-3)
767 (cons markdown-regex-header-4-atx 'markdown-header-face-4)
768 (cons markdown-regex-header-5-atx 'markdown-header-face-5)
769 (cons markdown-regex-header-6-atx 'markdown-header-face-6)
770 (cons markdown-regex-hr 'markdown-header-face)
771 '(markdown-match-comments 0 markdown-comment-face t t)
772 (cons markdown-regex-code '(2 markdown-inline-code-face))
773 (cons markdown-regex-list 'markdown-list-face)
774 (cons markdown-regex-link-inline
775 '((1 markdown-link-face t)
776 (2 markdown-url-face t)))
777 (cons markdown-regex-link-reference
778 '((1 markdown-link-face t)
779 (2 markdown-reference-face t)))
780 (cons markdown-regex-reference-definition
781 '((1 markdown-reference-face t)
782 (2 markdown-url-face t)
783 (3 markdown-link-title-face t)))
784 (cons markdown-regex-bold '(2 markdown-bold-face))
785 (cons markdown-regex-italic '(2 markdown-italic-face))
786 (cons markdown-regex-angle-uri 'markdown-link-face)
787 (cons markdown-regex-uri 'markdown-link-face)
788 (cons markdown-regex-email 'markdown-link-face)
790 "Syntax highlighting for Markdown files.")
792 (defconst markdown-mode-font-lock-keywords-latex
793 (list
794 ;; Math mode $..$ or $$..$$
795 (cons markdown-regex-latex-expression '(2 markdown-math-face))
796 ;; Display mode equations with brackets: \[ \]
797 (cons markdown-regex-latex-display 'markdown-math-face)
798 ;; Equation reference (eq:foo)
799 (cons "(eq:\\w+)" 'markdown-reference-face)
800 ;; Equation reference \eqref{foo}
801 (cons "\\\\eqref{\\w+}" 'markdown-reference-face))
802 "Syntax highlighting for LaTeX fragments.")
804 (defvar markdown-mode-font-lock-keywords
805 (append
806 (if markdown-enable-math
807 markdown-mode-font-lock-keywords-latex)
808 markdown-mode-font-lock-keywords-basic)
809 "Default highlighting expressions for Markdown mode.")
813 ;;; Markdown parsing functions ================================================
815 (defun markdown-cur-line-blank-p ()
816 "Return t if the current line is blank and nil otherwise."
817 (save-excursion
818 (beginning-of-line)
819 (re-search-forward "^\\s *$" (point-at-eol) t)))
821 (defun markdown-prev-line-blank-p ()
822 "Return t if the previous line is blank and nil otherwise.
823 If we are at the first line, then consider the previous line to be blank."
824 (save-excursion
825 (if (= (point-at-bol) (point-min))
827 (forward-line -1)
828 (markdown-cur-line-blank-p))))
830 (defun markdown-prev-line-indent-p ()
831 "Return t if the previous line is indented and nil otherwise."
832 (save-excursion
833 (forward-line -1)
834 (goto-char (point-at-bol))
835 (if (re-search-forward "^\\s " (point-at-eol) t) t)))
837 (defun markdown-cur-line-indent ()
838 "Return the number of leading whitespace characters in the current line."
839 (save-excursion
840 (goto-char (point-at-bol))
841 (re-search-forward "^\\s +" (point-at-eol) t)
842 (current-column)))
844 (defun markdown-prev-line-indent ()
845 "Return the number of leading whitespace characters in the previous line."
846 (save-excursion
847 (forward-line -1)
848 (markdown-cur-line-indent)))
850 (defun markdown-cur-non-list-indent ()
851 "Return the number of leading whitespace characters in the current line."
852 (save-excursion
853 (beginning-of-line)
854 (when (re-search-forward markdown-regex-list-indent (point-at-eol) t)
855 (current-column))))
857 (defun markdown-prev-non-list-indent ()
858 "Return position of the first non-list-marker on the previous line."
859 (save-excursion
860 (forward-line -1)
861 (markdown-cur-non-list-indent)))
863 (defun markdown--next-block ()
864 "Move the point to the start of the next text block."
865 (forward-line)
866 (while (and (or (not (markdown-prev-line-blank-p))
867 (markdown-cur-line-blank-p))
868 (not (eobp)))
869 (forward-line)))
871 (defun markdown--end-of-level (level)
872 "Move the point to the end of region with indentation at least LEVEL."
873 (let (indent)
874 (while (and (not (< (setq indent (markdown-cur-line-indent)) level))
875 (not (>= indent (+ level 4)))
876 (not (eobp)))
877 (markdown--next-block))
878 (unless (eobp)
879 ;; Move back before any trailing blank lines
880 (while (and (markdown-prev-line-blank-p)
881 (not (bobp)))
882 (forward-line -1))
883 (forward-line -1)
884 (end-of-line))))
886 ; From html-helper-mode
887 (defun markdown-match-comments (last)
888 "Match HTML comments from the point to LAST."
889 (cond ((search-forward "<!--" last t)
890 (backward-char 4)
891 (let ((beg (point)))
892 (cond ((search-forward-regexp "--[ \t]*>" last t)
893 (set-match-data (list beg (point)))
895 (t nil))))
896 (t nil)))
898 (defun markdown-match-pre-blocks (last)
899 "Match Markdown pre blocks from point to LAST.
900 A region matches as if it is indented at least four spaces
901 relative to the nearest previous block of lesser non-list-marker
902 indentation."
904 (let (cur-begin cur-end cur-indent prev-indent prev-list stop match found)
905 ;; Don't start in the middle of a block
906 (unless (and (bolp)
907 (markdown-prev-line-blank-p)
908 (not (markdown-cur-line-blank-p)))
909 (markdown--next-block))
911 ;; Move to the first full block in the region with indent 4 or more
912 (while (and (not (>= (setq cur-indent (markdown-cur-line-indent)) 4))
913 (not (>= (point) last)))
914 (markdown--next-block))
915 (setq cur-begin (point))
916 (markdown--end-of-level cur-indent)
917 (setq cur-end (point))
918 (setq match nil)
919 (setq stop (> cur-begin cur-end))
921 (while (and (<= cur-end last) (not stop) (not match))
922 ;; Move to the nearest preceding block of lesser (non-marker) indentation
923 (setq prev-indent (+ cur-indent 1))
924 (goto-char cur-begin)
925 (setq found nil)
926 (while (and (>= prev-indent cur-indent)
927 (not (and prev-list
928 (eq prev-indent cur-indent)))
929 (not (bobp)))
931 ;; Move point to the last line of the previous block.
932 (forward-line -1)
933 (while (and (markdown-cur-line-blank-p)
934 (not (bobp)))
935 (forward-line -1))
937 ;; Update the indentation level using either the
938 ;; non-list-marker indentation, if the previous line is the
939 ;; start of a list, or the actual indentation.
940 (setq prev-list (markdown-cur-non-list-indent))
941 (setq prev-indent (or prev-list
942 (markdown-cur-line-indent)))
943 (setq found t))
945 ;; If the loop didn't execute
946 (unless found
947 (setq prev-indent 0))
949 ;; Compare with prev-indent minus its remainder mod 4
950 (setq prev-indent (- prev-indent (mod prev-indent 4)))
952 ;; Set match data and return t if we have a match
953 (if (>= cur-indent (+ prev-indent 4))
954 ;; Match
955 (progn
956 (setq match t)
957 (set-match-data (list cur-begin cur-end))
958 ;; Leave point at end of block
959 (goto-char cur-end)
960 (forward-line))
962 ;; Move to the next block (if possible)
963 (goto-char cur-end)
964 (markdown--next-block)
965 (setq cur-begin (point))
966 (setq cur-indent (markdown-cur-line-indent))
967 (markdown--end-of-level cur-indent)
968 (setq cur-end (point))
969 (setq stop (equal cur-begin cur-end))))
970 match))
972 (defun markdown-font-lock-extend-region ()
973 "Extend the search region to include an entire block of text.
974 This helps improve font locking for block constructs such as pre blocks."
975 ;; Avoid compiler warnings about these global variables from font-lock.el.
976 ;; See the documentation for variable `font-lock-extend-region-functions'.
977 (eval-when-compile (defvar font-lock-beg) (defvar font-lock-end))
978 (save-excursion
979 (goto-char font-lock-beg)
980 (let ((found (re-search-backward "\n\n" nil t)))
981 (when found
982 (goto-char font-lock-end)
983 (when (re-search-forward "\n\n" nil t)
984 (beginning-of-line)
985 (setq font-lock-end (point)))
986 (setq font-lock-beg found)))))
990 ;;; Syntax Table ==============================================================
992 (defvar markdown-mode-syntax-table
993 (let ((markdown-mode-syntax-table (make-syntax-table)))
994 (modify-syntax-entry ?\" "w" markdown-mode-syntax-table)
995 markdown-mode-syntax-table)
996 "Syntax table for `markdown-mode'.")
1000 ;;; Element Insertion =========================================================
1002 (defun markdown-wrap-or-insert (s1 s2)
1003 "Insert the strings S1 and S2.
1004 If Transient Mark mode is on and a region is active, wrap the strings S1
1005 and S2 around the region."
1006 (if (and transient-mark-mode mark-active)
1007 (let ((a (region-beginning)) (b (region-end)))
1008 (goto-char a)
1009 (insert s1)
1010 (goto-char (+ b (length s1)))
1011 (insert s2))
1012 (insert s1 s2)))
1014 (defun markdown-insert-hr ()
1015 "Insert a horizonal rule using `markdown-hr-string'."
1016 (interactive)
1017 ;; Leading blank line
1018 (when (and (>= (point) (+ (point-min) 2))
1019 (not (looking-back "\n\n" 2)))
1020 (insert "\n"))
1021 ;; Insert custom HR string
1022 (insert (concat markdown-hr-string "\n"))
1023 ;; Following blank line
1024 (backward-char)
1025 (unless (looking-at "\n\n")
1026 (insert "\n")))
1028 (defun markdown-insert-bold ()
1029 "Insert markup for a bold word or phrase.
1030 If Transient Mark mode is on and a region is active, it is made bold."
1031 (interactive)
1032 (if markdown-bold-underscore
1033 (markdown-wrap-or-insert "__" "__")
1034 (markdown-wrap-or-insert "**" "**"))
1035 (backward-char 2))
1037 (defun markdown-insert-italic ()
1038 "Insert markup for an italic word or phrase.
1039 If Transient Mark mode is on and a region is active, it is made italic."
1040 (interactive)
1041 (if markdown-italic-underscore
1042 (markdown-wrap-or-insert "_" "_")
1043 (markdown-wrap-or-insert "*" "*"))
1044 (backward-char 1))
1046 (defun markdown-insert-code ()
1047 "Insert markup for an inline code fragment.
1048 If Transient Mark mode is on and a region is active, it is marked
1049 as inline code."
1050 (interactive)
1051 (markdown-wrap-or-insert "`" "`")
1052 (backward-char 1))
1054 (defun markdown-insert-link ()
1055 "Insert an inline link of the form []().
1056 If Transient Mark mode is on and a region is active, it is used
1057 as the link text."
1058 (interactive)
1059 (markdown-wrap-or-insert "[" "]")
1060 (insert "()")
1061 (backward-char 1))
1063 (defun markdown-insert-wiki-link ()
1064 "Insert a wiki link of the form [[WikiLink]].
1065 If Transient Mark mode is on and a region is active, it is used
1066 as the link text."
1067 (interactive)
1068 (markdown-wrap-or-insert "[[" "]]")
1069 (backward-char 2))
1071 (defun markdown-insert-image ()
1072 "Insert an inline image tag of the form ![]().
1073 If Transient Mark mode is on and a region is active, it is used
1074 as the alt text of the image."
1075 (interactive)
1076 (markdown-wrap-or-insert "![" "]")
1077 (insert "()")
1078 (backward-char 1))
1080 (defun markdown-insert-header-1 ()
1081 "Insert a first level atx-style (hash mark) header.
1082 If Transient Mark mode is on and a region is active, it is used
1083 as the header text."
1084 (interactive)
1085 (markdown-insert-header 1))
1087 (defun markdown-insert-header-2 ()
1088 "Insert a second level atx-style (hash mark) header.
1089 If Transient Mark mode is on and a region is active, it is used
1090 as the header text."
1091 (interactive)
1092 (markdown-insert-header 2))
1094 (defun markdown-insert-header-3 ()
1095 "Insert a third level atx-style (hash mark) header.
1096 If Transient Mark mode is on and a region is active, it is used
1097 as the header text."
1098 (interactive)
1099 (markdown-insert-header 3))
1101 (defun markdown-insert-header-4 ()
1102 "Insert a fourth level atx-style (hash mark) header.
1103 If Transient Mark mode is on and a region is active, it is used
1104 as the header text."
1105 (interactive)
1106 (markdown-insert-header 4))
1108 (defun markdown-insert-header-5 ()
1109 "Insert a fifth level atx-style (hash mark) header.
1110 If Transient Mark mode is on and a region is active, it is used
1111 as the header text."
1112 (interactive)
1113 (markdown-insert-header 5))
1115 (defun markdown-insert-header-6 ()
1116 "Insert a sixth level atx-style (hash mark) header.
1117 If Transient Mark mode is on and a region is active, it is used
1118 as the header text."
1119 (interactive)
1120 (markdown-insert-header 6))
1122 (defun markdown-insert-header (n)
1123 "Insert an atx-style (hash mark) header.
1124 With no prefix argument, insert a level-1 header. With prefix N,
1125 insert a level-N header. If Transient Mark mode is on and the
1126 region is active, it is used as the header text."
1127 (interactive "p")
1128 (unless n ; Test to see if n is defined
1129 (setq n 1)) ; Default to level 1 header
1130 (let (hdr hdrl hdrr)
1131 (dotimes (count n hdr)
1132 (setq hdr (concat "#" hdr))) ; Build a hash mark header string
1133 (setq hdrl (concat hdr " "))
1134 (setq hdrr (concat " " hdr))
1135 (markdown-wrap-or-insert hdrl hdrr))
1136 (backward-char (+ 1 n)))
1138 (defun markdown-insert-title ()
1139 "Insert a setext-style (underline) first level header.
1140 If Transient Mark mode is on and a region is active, it is used
1141 as the header text."
1142 (interactive)
1143 (if (and transient-mark-mode mark-active)
1144 (let ((a (region-beginning))
1145 (b (region-end))
1146 (len 0)
1147 (hdr))
1148 (setq len (- b a))
1149 (dotimes (count len hdr)
1150 (setq hdr (concat "=" hdr))) ; Build a === title underline
1151 (end-of-line)
1152 (insert "\n" hdr "\n"))
1153 (insert "\n==========\n")
1154 (backward-char 12)))
1156 (defun markdown-insert-section ()
1157 "Insert a setext-style (underline) second level header.
1158 If Transient Mark mode is on and a region is active, it is used
1159 as the header text."
1160 (interactive)
1161 (if (and transient-mark-mode mark-active)
1162 (let ((a (region-beginning))
1163 (b (region-end))
1164 (len 0)
1165 (hdr))
1166 (setq len (- b a))
1167 (dotimes (count len hdr)
1168 (setq hdr (concat "-" hdr))) ; Build a --- section underline
1169 (end-of-line)
1170 (insert "\n" hdr "\n"))
1171 (insert "\n----------\n")
1172 (backward-char 12)))
1174 (defun markdown-insert-blockquote ()
1175 "Start a blockquote section (or blockquote the region).
1176 If Transient Mark mode is on and a region is active, it is used as
1177 the blockquote text."
1178 (interactive)
1179 (if (and (boundp 'transient-mark-mode) transient-mark-mode mark-active)
1180 (markdown-blockquote-region (region-beginning) (region-end))
1181 (insert "> ")))
1183 (defun markdown-block-region (beg end prefix)
1184 "Format the region using a block prefix.
1185 Arguments BEG and END specify the beginning and end of the
1186 region. The characters PREFIX will appear at the beginning
1187 of each line."
1188 (if mark-active
1189 (save-excursion
1190 ;; Ensure that there is a leading blank line
1191 (goto-char beg)
1192 (when (and (>= (point) (+ (point-min) 2))
1193 (not (looking-back "\n\n" 2)))
1194 (insert "\n")
1195 (setq beg (1+ beg))
1196 (setq end (1+ end)))
1197 ;; Move back before any blank lines at the end
1198 (goto-char end)
1199 (while (and (looking-back "\n" 1)
1200 (not (equal (point) (point-min))))
1201 (backward-char)
1202 (setq end (1- end)))
1203 ;; Ensure that there is a trailing blank line
1204 (goto-char end)
1205 (if (not (or (looking-at "\n\n")
1206 (and (equal (1+ end) (point-max)) (looking-at "\n"))))
1207 (insert "\n"))
1208 ;; Insert PREFIX
1209 (goto-char beg)
1210 (beginning-of-line)
1211 (while (< (point-at-bol) end)
1212 (insert prefix)
1213 (setq end (+ (length prefix) end))
1214 (forward-line)))))
1216 (defun markdown-blockquote-region (beg end)
1217 "Blockquote the region.
1218 Arguments BEG and END specify the beginning and end of the region."
1219 (interactive "*r")
1220 (markdown-block-region beg end "> "))
1222 (defun markdown-insert-pre ()
1223 "Start a preformatted section (or apply to the region).
1224 If Transient Mark mode is on and a region is active, it is marked
1225 as preformatted text."
1226 (interactive)
1227 (if (and (boundp 'transient-mark-mode) transient-mark-mode mark-active)
1228 (markdown-pre-region (region-beginning) (region-end))
1229 (insert " ")))
1231 (defun markdown-pre-region (beg end)
1232 "Format the region as preformatted text.
1233 Arguments BEG and END specify the beginning and end of the region."
1234 (interactive "*r")
1235 (markdown-block-region beg end " "))
1237 ;;; Indentation ====================================================================
1239 (defun markdown-indent-find-next-position (cur-pos positions)
1240 "Return the position after the index of CUR-POS in POSITIONS."
1241 (while (and positions
1242 (not (equal cur-pos (car positions))))
1243 (setq positions (cdr positions)))
1244 (or (cadr positions) 0))
1246 (defun markdown-indent-line (&optional enter)
1247 "Indent the current line using some heuristics."
1248 (interactive)
1249 (let ((positions (markdown-calc-indents))
1250 (cur-pos (current-column)))
1251 (cond
1252 ;; When the enter key was pressed, indent to the default level.
1253 (enter
1254 (message "ENTER")
1255 (indent-line-to (car positions)))
1256 ;; Otherwise, cycle through the positions in sorted order.
1258 (setq positions (sort (delete-dups positions) '<))
1259 (indent-line-to
1260 (markdown-indent-find-next-position cur-pos positions))))))
1262 (defun markdown-calc-indents ()
1263 "Return a list of indentation columns to cycle through.
1264 The first element in the returned list should be considered the
1265 default indentation level."
1266 (let (pos prev-line-pos positions)
1268 ;; Previous line indent
1269 (setq prev-line-pos (markdown-prev-line-indent))
1270 (setq positions (cons prev-line-pos positions))
1272 ;; Previous non-list-marker indent
1273 (setq pos (markdown-prev-non-list-indent))
1274 (if pos
1275 (setq positions (cons pos positions)))
1277 ;; Indentation of the previous line + tab-width
1278 (cond
1279 (prev-line-pos
1280 (setq positions (cons (+ prev-line-pos tab-width) positions)))
1282 (setq positions (cons tab-width positions))))
1284 ;; Indentation of the previous line - tab-width
1285 (if (and prev-line-pos
1286 (> prev-line-pos tab-width))
1287 (setq positions (cons (- prev-line-pos tab-width) positions)))
1289 ;; Indentation of preceeding list item
1290 (setq pos
1291 (save-excursion
1292 (forward-line -1)
1293 (catch 'break
1294 (while (not (equal (point) (point-min)))
1295 (forward-line -1)
1296 (goto-char (point-at-bol))
1297 (when (re-search-forward markdown-regex-list-indent (point-at-eol) t)
1298 (throw 'break (length (match-string 1)))))
1299 nil)))
1300 (if (and pos (not (eq pos prev-line-pos)))
1301 (setq positions (cons pos positions)))
1303 ;; First column
1304 (setq positions (cons 0 positions))
1306 (reverse positions)))
1308 (defun markdown-do-normal-return ()
1309 "Insert a newline and optionally indent the next line."
1310 (newline)
1311 (if markdown-indent-on-enter
1312 (funcall indent-line-function 't)))
1314 (defun markdown-enter-key ()
1315 "Handle RET according to context.
1316 If there is a wiki link at the point, follow it unless
1317 `markdown-follow-wiki-link-on-enter' is nil. Otherwise, process
1318 it in the usual way."
1319 (interactive)
1320 (if (and markdown-follow-wiki-link-on-enter (markdown-wiki-link-p))
1321 (markdown-follow-wiki-link-at-point)
1322 (markdown-do-normal-return)))
1326 ;;; Keymap ====================================================================
1328 (defvar markdown-mode-map
1329 (let ((map (make-keymap)))
1330 ;; Element insertion
1331 (define-key map "\C-c\C-al" 'markdown-insert-link)
1332 (define-key map "\C-c\C-aw" 'markdown-insert-wiki-link)
1333 (define-key map "\C-c\C-ii" 'markdown-insert-image)
1334 (define-key map "\C-c\C-t1" 'markdown-insert-header-1)
1335 (define-key map "\C-c\C-t2" 'markdown-insert-header-2)
1336 (define-key map "\C-c\C-t3" 'markdown-insert-header-3)
1337 (define-key map "\C-c\C-t4" 'markdown-insert-header-4)
1338 (define-key map "\C-c\C-t5" 'markdown-insert-header-5)
1339 (define-key map "\C-c\C-t6" 'markdown-insert-header-6)
1340 (define-key map "\C-c\C-pb" 'markdown-insert-bold)
1341 (define-key map "\C-c\C-ss" 'markdown-insert-bold)
1342 (define-key map "\C-c\C-pi" 'markdown-insert-italic)
1343 (define-key map "\C-c\C-se" 'markdown-insert-italic)
1344 (define-key map "\C-c\C-pf" 'markdown-insert-code)
1345 (define-key map "\C-c\C-sc" 'markdown-insert-code)
1346 (define-key map "\C-c\C-sb" 'markdown-insert-blockquote)
1347 (define-key map "\C-c\C-s\C-b" 'markdown-blockquote-region)
1348 (define-key map "\C-c\C-sp" 'markdown-insert-pre)
1349 (define-key map "\C-c\C-s\C-p" 'markdown-pre-region)
1350 (define-key map "\C-c-" 'markdown-insert-hr)
1351 (define-key map "\C-c\C-tt" 'markdown-insert-title)
1352 (define-key map "\C-c\C-ts" 'markdown-insert-section)
1353 ;; WikiLink Following
1354 (define-key map "\C-c\C-f" 'markdown-follow-wiki-link-at-point)
1355 (define-key map "\M-n" 'markdown-next-wiki-link)
1356 (define-key map "\M-p" 'markdown-previous-wiki-link)
1357 ;; Indentation
1358 (define-key map "\C-m" 'markdown-enter-key)
1359 ;; Visibility cycling
1360 (define-key map (kbd "<tab>") 'markdown-cycle)
1361 (define-key map (kbd "<S-iso-lefttab>") 'markdown-shifttab)
1362 ;; Header navigation
1363 (define-key map (kbd "C-M-n") 'outline-next-visible-heading)
1364 (define-key map (kbd "C-M-p") 'outline-previous-visible-heading)
1365 (define-key map (kbd "C-M-f") 'outline-forward-same-level)
1366 (define-key map (kbd "C-M-b") 'outline-backward-same-level)
1367 (define-key map (kbd "C-M-u") 'outline-up-heading)
1368 ;; Markdown functions
1369 (define-key map "\C-c\C-cm" 'markdown)
1370 (define-key map "\C-c\C-cp" 'markdown-preview)
1371 (define-key map "\C-c\C-ce" 'markdown-export)
1372 (define-key map "\C-c\C-cv" 'markdown-export-and-view)
1373 ;; References
1374 (define-key map "\C-c\C-cc" 'markdown-check-refs)
1375 map)
1376 "Keymap for Markdown major mode.")
1378 ;;; Menu ==================================================================
1380 (easy-menu-define markdown-mode-menu markdown-mode-map
1381 "Menu for Markdown mode"
1382 '("Markdown"
1383 ("Show/Hide"
1384 ["Cycle visibility" markdown-cycle (outline-on-heading-p)]
1385 ["Cycle global visibility" markdown-shifttab])
1386 "---"
1387 ["Compile" markdown]
1388 ["Preview" markdown-preview]
1389 ["Export" markdown-export]
1390 ["Export & View" markdown-export-and-view]
1391 "---"
1392 ("Headers (setext)"
1393 ["Insert Title" markdown-insert-title]
1394 ["Insert Section" markdown-insert-section])
1395 ("Headers (atx)"
1396 ["First level" markdown-insert-header-1]
1397 ["Second level" markdown-insert-header-2]
1398 ["Third level" markdown-insert-header-3]
1399 ["Fourth level" markdown-insert-header-4]
1400 ["Fifth level" markdown-insert-header-5]
1401 ["Sixth level" markdown-insert-header-6])
1402 "---"
1403 ["Bold" markdown-insert-bold]
1404 ["Italic" markdown-insert-italic]
1405 ["Blockquote" markdown-insert-blockquote]
1406 ["Preformatted" markdown-insert-pre]
1407 ["Code" markdown-insert-code]
1408 "---"
1409 ["Insert inline link" markdown-insert-link]
1410 ["Insert image" markdown-insert-image]
1411 ["Insert horizontal rule" markdown-insert-hr]
1412 "---"
1413 ["Check references" markdown-check-refs]
1414 "---"
1415 ["Version" markdown-show-version]
1420 ;;; References ================================================================
1422 ;;; Undefined reference checking code by Dmitry Dzhus <mail@sphinx.net.ru>.
1424 (defconst markdown-refcheck-buffer
1425 "*Undefined references for %BUFFER%*"
1426 "Pattern for name of buffer for listing undefined references.
1427 The string %BUFFER% will be replaced by the corresponding
1428 `markdown-mode' buffer name.")
1430 (defun markdown-has-reference-definition (reference)
1431 "Find out whether Markdown REFERENCE is defined.
1433 REFERENCE should include the square brackets, like [this]."
1434 (let ((reference (downcase reference)))
1435 (save-excursion
1436 (goto-char (point-min))
1437 (catch 'found
1438 (while (re-search-forward markdown-regex-reference-definition nil t)
1439 (when (string= reference (downcase (match-string-no-properties 1)))
1440 (throw 'found t)))))))
1442 (defun markdown-get-undefined-refs ()
1443 "Return a list of undefined Markdown references.
1445 Result is an alist of pairs (reference . occurencies), where
1446 occurencies is itself another alist of pairs (label .
1447 line-number).
1449 For example, an alist corresponding to [Nice editor][Emacs] at line 12,
1450 \[GNU Emacs][Emacs] at line 45 and [manual][elisp] at line 127 is
1451 \((\"[emacs]\" (\"[Nice editor]\" . 12) (\"[GNU Emacs]\" . 45)) (\"[elisp]\" (\"[manual]\" . 127)))."
1452 (let ((missing))
1453 (save-excursion
1454 (goto-char (point-min))
1455 (while
1456 (re-search-forward markdown-regex-link-reference nil t)
1457 (let* ((label (match-string-no-properties 1))
1458 (reference (match-string-no-properties 2))
1459 (target (downcase (if (string= reference "[]") label reference))))
1460 (unless (markdown-has-reference-definition target)
1461 (let ((entry (assoc target missing)))
1462 (if (not entry)
1463 (add-to-list 'missing (cons target
1464 (list (cons label (markdown-line-number-at-pos)))) t)
1465 (setcdr entry
1466 (append (cdr entry) (list (cons label (markdown-line-number-at-pos))))))))))
1467 missing)))
1469 (defun markdown-add-missing-ref-definition (ref buffer &optional recheck)
1470 "Add blank REF definition to the end of BUFFER.
1472 REF is a Markdown reference in square brackets, like \"[lisp-history]\".
1474 When RECHECK is non-nil, BUFFER gets rechecked for undefined
1475 references so that REF disappears from the list of those links."
1476 (with-current-buffer buffer
1477 (when (not (eq major-mode 'markdown-mode))
1478 (error "Not available in current mode"))
1479 (goto-char (point-max))
1480 (indent-new-comment-line)
1481 (insert (concat ref ": ")))
1482 (switch-to-buffer-other-window buffer)
1483 (goto-char (point-max))
1484 (when recheck
1485 (markdown-check-refs t)))
1487 ;; Button which adds an empty Markdown reference definition to the end
1488 ;; of buffer specified as its 'target-buffer property. Reference name
1489 ;; is button's label
1490 (when (>= emacs-major-version 22)
1491 (define-button-type 'markdown-ref-button
1492 'help-echo "Push to create an empty reference definition"
1493 'face 'bold
1494 'action (lambda (b)
1495 (markdown-add-missing-ref-definition
1496 (button-label b) (button-get b 'target-buffer) t))))
1498 ;; Button jumping to line in buffer specified as its 'target-buffer
1499 ;; property. Line number is button's 'line property.
1500 (when (>= emacs-major-version 22)
1501 (define-button-type 'goto-line-button
1502 'help-echo "Push to go to this line"
1503 'face 'italic
1504 'action (lambda (b)
1505 (message (button-get b 'buffer))
1506 (switch-to-buffer-other-window (button-get b 'target-buffer))
1507 ;; use call-interactively to silence compiler
1508 (call-interactively 'goto-line (button-get b 'target-line)))))
1510 (defun markdown-check-refs (&optional silent)
1511 "Show all undefined Markdown references in current `markdown-mode' buffer.
1513 If SILENT is non-nil, do not message anything when no undefined
1514 references found.
1516 Links which have empty reference definitions are considered to be
1517 defined."
1518 (interactive "P")
1519 (when (not (eq major-mode 'markdown-mode))
1520 (error "Not available in current mode"))
1521 (let ((oldbuf (current-buffer))
1522 (refs (markdown-get-undefined-refs))
1523 (refbuf (get-buffer-create (replace-regexp-in-string
1524 "%BUFFER%" (buffer-name)
1525 markdown-refcheck-buffer t))))
1526 (if (null refs)
1527 (progn
1528 (when (not silent)
1529 (message "No undefined references found"))
1530 (kill-buffer refbuf))
1531 (with-current-buffer refbuf
1532 (when view-mode
1533 (View-exit-and-edit))
1534 (erase-buffer)
1535 (insert "Following references lack definitions:")
1536 (newline 2)
1537 (dolist (ref refs)
1538 (let ((button-label (format "%s" (car ref))))
1539 (if (>= emacs-major-version 22)
1540 ;; Create a reference button in Emacs 22
1541 (insert-text-button button-label
1542 :type 'markdown-ref-button
1543 'target-buffer oldbuf)
1544 ;; Insert reference as text in Emacs < 22
1545 (insert button-label)))
1546 (insert " (")
1547 (dolist (occurency (cdr ref))
1548 (let ((line (cdr occurency)))
1549 (if (>= emacs-major-version 22)
1550 ;; Create a line number button in Emacs 22
1551 (insert-button (number-to-string line)
1552 :type 'goto-line-button
1553 'target-buffer oldbuf
1554 'target-line line)
1555 ;; Insert line number as text in Emacs < 22
1556 (insert (number-to-string line)))
1557 (insert " "))) (delete-char -1)
1558 (insert ")")
1559 (newline))
1560 (view-buffer-other-window refbuf)
1561 (goto-char (point-min))
1562 (forward-line 2)))))
1564 ;;; Outline ===================================================================
1566 ;; The following visibility cycling code was taken from org-mode
1567 ;; by Carsten Dominik and adapted for markdown-mode.
1569 (defvar markdown-cycle-global-status 1)
1570 (defvar markdown-cycle-subtree-status nil)
1572 ;; Based on org-end-of-subtree from org.el
1573 (defun markdown-end-of-subtree (&optional invisible-OK)
1574 "Move to the end of the current subtree.
1575 Only visible heading lines are considered, unless INVISIBLE-OK is
1576 non-nil."
1577 (outline-back-to-heading invisible-OK)
1578 (let ((first t)
1579 (level (funcall outline-level)))
1580 (while (and (not (eobp))
1581 (or first (> (funcall outline-level) level)))
1582 (setq first nil)
1583 (outline-next-heading))
1584 (if (memq (preceding-char) '(?\n ?\^M))
1585 (progn
1586 ;; Go to end of line before heading
1587 (forward-char -1)
1588 (if (memq (preceding-char) '(?\n ?\^M))
1589 ;; leave blank line before heading
1590 (forward-char -1)))))
1591 (point))
1593 ;; Based on org-cycle from org.el.
1594 (defun markdown-cycle (&optional arg)
1595 "Visibility cycling for Markdown mode.
1596 If ARG is t, perform global visibility cycling. If the point is
1597 at an atx-style header, cycle visibility of the corresponding
1598 subtree. Otherwise, insert a tab using `indent-relative'."
1599 (interactive "P")
1600 (cond
1601 ((eq arg t) ;; Global cycling
1602 (cond
1603 ((and (eq last-command this-command)
1604 (eq markdown-cycle-global-status 2))
1605 ;; Move from overview to contents
1606 (hide-sublevels 1)
1607 (message "CONTENTS")
1608 (setq markdown-cycle-global-status 3))
1610 ((and (eq last-command this-command)
1611 (eq markdown-cycle-global-status 3))
1612 ;; Move from contents to all
1613 (show-all)
1614 (message "SHOW ALL")
1615 (setq markdown-cycle-global-status 1))
1618 ;; Defaults to overview
1619 (hide-body)
1620 (message "OVERVIEW")
1621 (setq markdown-cycle-global-status 2))))
1623 ((save-excursion (beginning-of-line 1) (looking-at outline-regexp))
1624 ;; At a heading: rotate between three different views
1625 (outline-back-to-heading)
1626 (let ((goal-column 0) eoh eol eos)
1627 ;; Determine boundaries
1628 (save-excursion
1629 (outline-back-to-heading)
1630 (save-excursion
1631 (beginning-of-line 2)
1632 (while (and (not (eobp)) ;; this is like `next-line'
1633 (get-char-property (1- (point)) 'invisible))
1634 (beginning-of-line 2)) (setq eol (point)))
1635 (outline-end-of-heading) (setq eoh (point))
1636 (markdown-end-of-subtree t)
1637 (skip-chars-forward " \t\n")
1638 (beginning-of-line 1) ; in case this is an item
1639 (setq eos (1- (point))))
1640 ;; Find out what to do next and set `this-command'
1641 (cond
1642 ((= eos eoh)
1643 ;; Nothing is hidden behind this heading
1644 (message "EMPTY ENTRY")
1645 (setq markdown-cycle-subtree-status nil))
1646 ((>= eol eos)
1647 ;; Entire subtree is hidden in one line: open it
1648 (show-entry)
1649 (show-children)
1650 (message "CHILDREN")
1651 (setq markdown-cycle-subtree-status 'children))
1652 ((and (eq last-command this-command)
1653 (eq markdown-cycle-subtree-status 'children))
1654 ;; We just showed the children, now show everything.
1655 (show-subtree)
1656 (message "SUBTREE")
1657 (setq markdown-cycle-subtree-status 'subtree))
1659 ;; Default action: hide the subtree.
1660 (hide-subtree)
1661 (message "FOLDED")
1662 (setq markdown-cycle-subtree-status 'folded)))))
1665 (funcall indent-line-function))))
1667 ;; Based on org-shifttab from org.el.
1668 (defun markdown-shifttab ()
1669 "Global visibility cycling.
1670 Calls `markdown-cycle' with argument t."
1671 (interactive)
1672 (markdown-cycle t))
1674 ;;; Commands ==================================================================
1676 (defun markdown (&optional output-buffer-name)
1677 "Run `markdown' on current buffer and insert output in buffer BUFFER-OUTPUT."
1678 (interactive)
1679 (let ((title (buffer-name))
1680 (begin-region)
1681 (end-region))
1682 (if (and (boundp 'transient-mark-mode) transient-mark-mode mark-active)
1683 (setq begin-region (region-beginning)
1684 end-region (region-end))
1685 (setq begin-region (point-min)
1686 end-region (point-max)))
1688 (unless output-buffer-name
1689 (setq output-buffer-name markdown-output-buffer-name))
1691 (if markdown-command-needs-filename
1692 ;; Handle case when `markdown-command' does not read from stdin
1693 (if (not buffer-file-name)
1694 (error "Must be visiting a file")
1695 (shell-command (concat markdown-command " " buffer-file-name)
1696 output-buffer-name))
1697 ;; Pass region to `markdown-command' via stdin
1698 (shell-command-on-region begin-region end-region markdown-command
1699 output-buffer-name))
1701 ;; Add header and footer and switch to html-mode.
1702 (save-current-buffer
1703 (set-buffer output-buffer-name)
1704 (goto-char (point-min))
1705 (unless (markdown-output-standalone-p)
1706 (markdown-add-xhtml-header-and-footer title))
1707 (html-mode))
1709 ;; Ensure buffer gets raised, even with short command output
1710 (switch-to-buffer-other-window output-buffer-name)))
1712 (defun markdown-output-standalone-p ()
1713 "Determine whether `markdown-command' output is standalone XHTML.
1714 Standalone XHTML output is identified by an occurrence of
1715 `markdown-xhtml-standalone-regexp' in the first five lines of output."
1716 (re-search-forward
1717 markdown-xhtml-standalone-regexp
1718 (save-excursion (goto-char (point-min)) (forward-line 4) (point))
1721 (defun markdown-add-xhtml-header-and-footer (title)
1722 "Wrap XHTML header and footer with given TITLE around current buffer."
1723 (insert "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"
1724 "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"\n"
1725 "\t\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n\n"
1726 "<html xmlns=\"http://www.w3.org/1999/xhtml\">\n\n"
1727 "<head>\n<title>")
1728 (insert title)
1729 (insert "</title>\n")
1730 (if (> (length markdown-css-path) 0)
1731 (insert "<link rel=\"stylesheet\" type=\"text/css\" media=\"all\" href=\""
1732 markdown-css-path
1733 "\" />\n"))
1734 (when (> (length markdown-xhtml-header-content) 0)
1735 (insert markdown-xhtml-header-content))
1736 (insert "\n</head>\n\n"
1737 "<body>\n\n")
1738 (goto-char (point-max))
1739 (insert "\n"
1740 "</body>\n"
1741 "</html>\n"))
1743 (defun markdown-preview ()
1744 "Run `markdown' on the current buffer and preview the output in a browser."
1745 (interactive)
1746 (markdown markdown-output-buffer-name)
1747 (browse-url-of-buffer markdown-output-buffer-name))
1749 (defun markdown-export-file-name ()
1750 "Attempt to generate a filename for Markdown output.
1751 If the current buffer is visiting a file, we construct a new
1752 output filename based on that filename. Otherwise, return nil."
1753 (when (buffer-file-name)
1754 (concat (file-name-sans-extension (buffer-file-name)) ".html")))
1756 (defun markdown-export ()
1757 "Run Markdown on the current buffer, save to a file, and return the filename.
1758 The resulting filename will be constructed using the current filename, but
1759 with the extension removed and replaced with .html."
1760 (interactive)
1761 (let ((output-file (markdown-export-file-name))
1762 (output-buffer-name))
1763 (when output-file
1764 (setq output-buffer-name (buffer-name (find-file-noselect output-file)))
1765 (markdown output-buffer-name)
1766 (with-current-buffer output-buffer-name
1767 (save-buffer)
1768 (kill-buffer-and-window))
1769 output-file)))
1771 (defun markdown-export-and-view ()
1772 "Export to XHTML using `markdown-export' and browse the resulting file."
1773 (interactive)
1774 (browse-url (markdown-export)))
1776 ;;; WikiLink Following/Markup =================================================
1778 (require 'thingatpt)
1780 (defun markdown-wiki-link-p ()
1781 "Return non-nil when `point' is at a true wiki link.
1782 A true wiki link name matches `markdown-regex-wiki-link' but does not
1783 match the current file name after conversion. This modifies the data
1784 returned by `match-data'. Note that the potential wiki link name must
1785 be available via `match-string'."
1786 (let ((case-fold-search nil))
1787 (and (thing-at-point-looking-at markdown-regex-wiki-link)
1788 (or (not buffer-file-name)
1789 (not (string-equal (buffer-file-name)
1790 (markdown-convert-wiki-link-to-filename
1791 (match-string 1)))))
1792 (not (save-match-data
1793 (save-excursion))))))
1795 (defun markdown-convert-wiki-link-to-filename (name)
1796 "Generate a filename from the wiki link NAME.
1797 Spaces are converted to underscores, following the convention
1798 used by the Python Markdown WikiLinks extension."
1799 (let ((new-ext (file-name-extension (buffer-file-name)))
1800 (new-basename (replace-regexp-in-string "[[:space:]\n]" "_" name)))
1801 (concat new-basename "." new-ext)))
1803 (defun markdown-follow-wiki-link (name)
1804 "Follow the wiki link NAME.
1805 Convert the name to a file name and call `find-file'. Ensure that
1806 the new buffer remains in `markdown-mode'."
1807 (let ((filename (markdown-convert-wiki-link-to-filename name)))
1808 (find-file filename))
1809 (markdown-mode))
1811 (defun markdown-follow-wiki-link-at-point ()
1812 "Find Wiki Link at point.
1813 See `markdown-wiki-link-p' and `markdown-follow-wiki-link'."
1814 (interactive)
1815 (if (markdown-wiki-link-p)
1816 (markdown-follow-wiki-link (match-string 1))
1817 (error "Point is not at a Wiki Link")))
1819 (defun markdown-next-wiki-link ()
1820 "Jump to next wiki link.
1821 See `markdown-wiki-link-p'."
1822 (interactive)
1823 (if (markdown-wiki-link-p)
1824 ; At a wiki link already, move past it.
1825 (goto-char (+ 1 (match-end 0))))
1826 (save-match-data
1827 ; Search for the next wiki link and move to the beginning.
1828 (re-search-forward markdown-regex-wiki-link nil t)
1829 (goto-char (match-beginning 0))))
1831 (defun markdown-previous-wiki-link ()
1832 "Jump to previous wiki link.
1833 See `markdown-wiki-link-p'."
1834 (interactive)
1835 (re-search-backward markdown-regex-wiki-link nil t))
1837 (defun markdown-highlight-wiki-link (from to face)
1838 "Highlight the wiki link in the region between FROM and TO using FACE."
1839 (let ((ov (make-overlay from to)))
1840 (overlay-put ov 'face face)))
1842 (defun markdown-unfontify-region-wiki-links (from to)
1843 "Remove wiki link faces from the region specified by FROM and TO."
1844 (interactive "nfrom: \nnto: ")
1845 (remove-overlays from to 'face markdown-link-face)
1846 (remove-overlays from to 'face markdown-missing-link-face))
1848 (defun markdown-fontify-region-wiki-links (from to)
1849 "Search region given by FROM and TO for wiki links and fontify them.
1850 If a wiki link is found check to see if the backing file exists
1851 and highlight accordingly."
1852 (goto-char from)
1853 (while (re-search-forward markdown-regex-wiki-link to t)
1854 (let ((highlight-beginning (match-beginning 0))
1855 (highlight-end (match-end 0))
1856 (file-name
1857 (markdown-convert-wiki-link-to-filename (match-string 1))))
1858 (if (file-exists-p file-name)
1859 (markdown-highlight-wiki-link
1860 highlight-beginning highlight-end markdown-link-face)
1861 (markdown-highlight-wiki-link
1862 highlight-beginning highlight-end markdown-missing-link-face)))))
1864 (defun markdown-extend-changed-region (from to)
1865 "Extend region given by FROM and TO so that we can fontify all links.
1866 The region is extended to the first newline before and the first
1867 newline after."
1868 ;; start looking for the first new line before 'from
1869 (goto-char from)
1870 (re-search-backward "\n" nil t)
1871 (let ((new-from (point-min))
1872 (new-to (point-max)))
1873 (if (not (= (point) from))
1874 (setq new-from (point)))
1875 ;; do the same thing for the first new line after 'to
1876 (goto-char to)
1877 (re-search-forward "\n" nil t)
1878 (if (not (= (point) to))
1879 (setq new-to (point)))
1880 (list new-from new-to)))
1882 (defun markdown-check-change-for-wiki-link (from to change)
1883 "Check region between FROM and TO for wiki links and re-fontfy as needed.
1884 Designed to be used with the `after-change-functions' hook.
1885 CHANGE is the number of bytes of pre-change text replaced by the
1886 given range."
1887 (interactive "nfrom: \nnto: \nnchange: ")
1888 (let* ((inhibit-point-motion-hooks t)
1889 (inhibit-quit t)
1890 (modified (buffer-modified-p))
1891 (buffer-undo-list t)
1892 (inhibit-read-only t)
1893 (inhibit-point-motion-hooks t)
1894 (inhibit-modification-hooks t)
1895 (current-point (point))
1896 deactivate-mark)
1897 (unwind-protect
1898 (save-restriction
1899 ;; Extend the region to fontify so that it starts
1900 ;; and ends at safe places.
1901 (multiple-value-bind (new-from new-to)
1902 (markdown-extend-changed-region from to)
1903 ;; Unfontify existing fontification (start from scratch)
1904 (markdown-unfontify-region-wiki-links new-from new-to)
1905 ;; Now do the fontification.
1906 (markdown-fontify-region-wiki-links new-from new-to)))
1907 (unless modified
1908 (restore-buffer-modified-p nil)))
1909 (goto-char current-point)))
1911 (defun markdown-fontify-buffer-wiki-links ()
1912 "Refontify all wiki links in the buffer."
1913 (interactive)
1914 (markdown-check-change-for-wiki-link (point-min) (point-max) 0))
1916 ;;; Miscellaneous =============================================================
1918 (defun markdown-line-number-at-pos (&optional pos)
1919 "Return (narrowed) buffer line number at position POS.
1920 If POS is nil, use current buffer location.
1921 This is an exact copy of `line-number-at-pos' for use in emacs21."
1922 (let ((opoint (or pos (point))) start)
1923 (save-excursion
1924 (goto-char (point-min))
1925 (setq start (point))
1926 (goto-char opoint)
1927 (forward-line 0)
1928 (1+ (count-lines start (point))))))
1930 (defun markdown-nobreak-p ()
1931 "Return nil if it is acceptable to break the current line at the point."
1932 ;; inside in square brackets (e.g., link anchor text)
1933 (looking-back "\\[[^]]*"))
1937 ;;; Mode definition ==========================================================
1939 (defun markdown-show-version ()
1940 "Show the version number in the minibuffer."
1941 (interactive)
1942 (message "markdown-mode, version %s" markdown-mode-version))
1944 ;;;###autoload
1945 (define-derived-mode markdown-mode text-mode "Markdown"
1946 "Major mode for editing Markdown files."
1947 ;; Natural Markdown tab width
1948 (setq tab-width 4)
1949 ;; Comments
1950 (make-local-variable 'comment-start)
1951 (setq comment-start "<!-- ")
1952 (make-local-variable 'comment-end)
1953 (setq comment-end " -->")
1954 (make-local-variable 'comment-start-skip)
1955 (setq comment-start-skip "<!--[ \t]*")
1956 (make-local-variable 'comment-column)
1957 (setq comment-column 0)
1958 ;; Font lock.
1959 (set (make-local-variable 'font-lock-defaults)
1960 '(markdown-mode-font-lock-keywords))
1961 (set (make-local-variable 'font-lock-multiline) t)
1962 ;; For menu support in XEmacs
1963 (easy-menu-add markdown-mode-menu markdown-mode-map)
1964 ;; Make filling work with lists (unordered, ordered, and definition)
1965 (set (make-local-variable 'paragraph-start)
1966 "\f\\|[ \t]*$\\|^[ \t]*[*+-] \\|^[ \t*][0-9]+\\.\\|^[ \t]*: ")
1967 ;; Outline mode
1968 (make-local-variable 'outline-regexp)
1969 (setq outline-regexp "#+")
1970 ;; Cause use of ellipses for invisible text.
1971 (add-to-invisibility-spec '(outline . t))
1972 ;; Indentation and filling
1973 (make-local-variable 'fill-nobreak-predicate)
1974 (add-hook 'fill-nobreak-predicate 'markdown-nobreak-p)
1975 (setq indent-line-function markdown-indent-function)
1977 ;; Prepare hooks for XEmacs compatibility
1978 (when (featurep 'xemacs)
1979 (make-local-hook 'after-change-functions)
1980 (make-local-hook 'font-lock-extend-region-functions)
1981 (make-local-hook 'window-configuration-change-hook))
1983 ;; Multiline font lock
1984 (add-hook 'font-lock-extend-region-functions
1985 'markdown-font-lock-extend-region)
1987 ;; Anytime text changes make sure it gets fontified correctly
1988 (add-hook 'after-change-functions 'markdown-check-change-for-wiki-link t t)
1990 ;; If we left the buffer there is a really good chance we were
1991 ;; creating one of the wiki link documents. Make sure we get
1992 ;; refontified when we come back.
1993 (add-hook 'window-configuration-change-hook
1994 'markdown-fontify-buffer-wiki-links t t)
1996 ;; do the initial link fontification
1997 (markdown-fontify-buffer-wiki-links))
1999 ;(add-to-list 'auto-mode-alist '("\\.text$" . markdown-mode))
2001 ;;; GitHub Flavored Markdown Mode ============================================
2003 (define-derived-mode gfm-mode markdown-mode "GFM"
2004 "Major mode for editing GitHub Flavored Markdown files."
2005 (auto-fill-mode 0)
2006 (longlines-mode 1))
2008 (provide 'markdown-mode)
2010 ;;; markdown-mode.el ends here