Document markdown-footnote-kill
[markdown-mode.git] / markdown-mode.el
blobc018cdc0b72c21553db80e06ccf69e5e352cc302
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>
17 ;; Copyright (C) 2011 Christopher J. Madsen <cjm@cjmweb.net>
18 ;; Copyright (C) 2011 Shigeru Fukaya <shigeru.fukaya@gmail.com>
19 ;; Copyright (C) 2011 Joost Kremers <joostkremers@fastmail.fm>
21 ;; Author: Jason R. Blevins <jrblevin@sdf.org>
22 ;; Maintainer: Jason R. Blevins <jrblevin@sdf.org>
23 ;; Created: May 24, 2007
24 ;; Version: 1.8.1
25 ;; Keywords: Markdown, GitHub Flavored Markdown, itex
26 ;; URL: http://jblevins.org/projects/markdown-mode/
28 ;; This file is not part of GNU Emacs.
30 ;; This program is free software; you can redistribute it and/or modify
31 ;; it under the terms of the GNU General Public License as published by
32 ;; the Free Software Foundation; either version 2, or (at your option)
33 ;; any later version.
35 ;; This program is distributed in the hope that it will be useful,
36 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
37 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
38 ;; GNU General Public License for more details.
40 ;; You should have received a copy of the GNU General Public License
41 ;; along with this program; if not, write to the Free Software
42 ;; Foundation, Inc., 51 Franklin Street, Fifth Floor,
43 ;; Boston, MA 02110-1301, USA.
45 ;;; Commentary:
47 ;; markdown-mode is a major mode for editing [Markdown][]-formatted
48 ;; text files in GNU Emacs. markdown-mode is free software, licensed
49 ;; under the GNU GPL.
51 ;; [Markdown]: http://daringfireball.net/projects/markdown/
53 ;; The latest stable version is markdown-mode 1.8.1, released on August 15, 2011:
55 ;; * [markdown-mode.el][]
56 ;; * [Screenshot][]
57 ;; * [Release notes][]
59 ;; [markdown-mode.el]: http://jblevins.org/projects/markdown-mode/markdown-mode.el
60 ;; [screenshot]: http://jblevins.org/projects/markdown-mode/screenshots/20110812-001.png
61 ;; [release notes]: http://jblevins.org/projects/markdown-mode/rev-1-8-1
63 ;; markdown-mode is also available in several package managers, including:
65 ;; * Debian and Ubuntu Linux: [emacs-goodies-el][]
66 ;; * RedHat and Fedora Linux: [emacs-goodies][]
67 ;; * OpenBSD: [textproc/markdown-mode][]
68 ;; * Arch Linux (AUR): [emacs-markdown-mode-git][]
70 ;; [emacs-goodies-el]: http://packages.debian.org/emacs-goodies-el
71 ;; [emacs-goodies]: https://admin.fedoraproject.org/pkgdb/acls/name/emacs-goodies
72 ;; [textproc/markdown-mode]: http://pkgsrc.se/textproc/markdown-mode
73 ;; [emacs-markdown-mode-git]: http://aur.archlinux.org/packages.php?ID=30389
75 ;; The latest development version can be downloaded directly
76 ;; ([markdown-mode.el][devel.el]) or it can be obtained from the
77 ;; (browsable and clonable) Git repository at
78 ;; <http://jblevins.org/git/markdown-mode.git>. The entire repository,
79 ;; including the full project history, can be cloned via the Git protocol
80 ;; by running
82 ;; git clone git://jblevins.org/git/markdown-mode.git
84 ;; [devel.el]: http://jblevins.org/git/markdown-mode.git/plain/markdown-mode.el
86 ;;; Dependencies:
88 ;; markdown-mode requires easymenu, a standard package since GNU Emacs
89 ;; 19 and XEmacs 19, which provides a uniform interface for creating
90 ;; menus in GNU Emacs and XEmacs.
92 ;;; Installation:
94 ;; Make sure to place `markdown-mode.el` somewhere in the load-path and add
95 ;; the following lines to your `.emacs` file to associate markdown-mode
96 ;; with `.text` files:
98 ;; (autoload 'markdown-mode "markdown-mode"
99 ;; "Major mode for editing Markdown files" t)
100 ;; (setq auto-mode-alist
101 ;; (cons '("\\.text" . markdown-mode) auto-mode-alist))
103 ;; There is no consensus on an official file extension so change `.text` to
104 ;; `.mdwn`, `.md`, `.mdt`, or whatever you call your markdown files.
106 ;;; Customization:
108 ;; Although no configuration is *necessary* there are a few things
109 ;; that can be customized. The `M-x customize-mode` command
110 ;; provides an interface to all of the possible customizations:
112 ;; * `markdown-command' - the command used to run Markdown (default:
113 ;; `markdown'). This variable may be customized to pass
114 ;; command-line options to your Markdown processor of choice, but
115 ;; this command must accept input from `stdin`. If it does not, a
116 ;; simple wrapper script can be used to write `stdin` to a file
117 ;; and then pass that file to your Markdown interpreter. Ideally,
118 ;; this command will produce an XHTML fragment around which
119 ;; markdown-mode will wrap a header and footer (which can be
120 ;; further customized). However, it attempts to detect whether
121 ;; the command produces standalone XHTML output (via
122 ;; `markdown-xhtml-standalone-regexp'), in which case no header
123 ;; and footer content will be added.
125 ;; * `markdown-command-needs-filename' - set to non-nil if
126 ;; `markdown-command' does not accept input from stdin (default: nil).
127 ;; Instead, it will be passed a filename as the final command-line
128 ;; option. As a result, you will only be able to run Markdown
129 ;; from buffers which are visiting a file.
131 ;; * `markdown-hr-string' - string to use when inserting horizontal
132 ;; rules (default: `* * * * *').
134 ;; * `markdown-bold-underscore' - set to a non-nil value to use two
135 ;; underscores for bold instead of two asterisks (default: `nil').
137 ;; * `markdown-italic-underscore' - set to a non-nil value to use
138 ;; underscores for italic instead of asterisks (default: `nil').
140 ;; * `markdown-indent-function' - the function to use for automatic
141 ;; indentation (default: `markdown-indent-line').
143 ;; * `markdown-indent-on-enter' - set to a non-nil value to
144 ;; automatically indent new lines when the enter key is pressed
145 ;; (default: `t')
147 ;; * `markdown-follow-wiki-link-on-enter' - set to a non-nil value
148 ;; to automatically open a linked document in a new buffer if the
149 ;; cursor is an wiki link
150 ;; (default: `t')
152 ;; * `markdown-wiki-link-alias-first' - set to a non-nil value to
153 ;; treat aliased wiki links like `[[link text|PageName]]`.
154 ;; When set to nil, they will be treated as `[[PageName|link text]]'.
156 ;; * `markdown-uri-types' - a list of protocols for URIs that
157 ;; `markdown-mode' should highlight.
159 ;; * `markdown-enable-math' - syntax highlighting for
160 ;; LaTeX fragments (default: `nil').
162 ;; * `markdown-css-path' - CSS file to link to in XHTML output.
164 ;; * `markdown-xhtml-header-content' - additional content to include
165 ;; in the XHTML `<head>` block.
167 ;; * `markdown-xhtml-standalone-regexp' - a regular expression which
168 ;; indicates whether the output of `markdown-command' is standalone
169 ;; XHTML (default: `^\\(\<\?xml\\|\<!DOCTYPE\\|\<html\\)`). If
170 ;; this is not matched, we assume this output is a fragment and add
171 ;; our own header and footer.
173 ;; * `markdown-link-space-sub-char' - a character to replace spaces
174 ;; when mapping wiki links to filenames (default: `_`).
175 ;; For example, use an underscore for compatibility with the
176 ;; Python Markdown WikiLinks extension or a hyphen for compatibility
177 ;; with Github wiki links.
179 ;; Additionally, the faces used for syntax highlighting can be modified to
180 ;; your liking by issuing `M-x customize-group RET markdown-faces`
181 ;; or by using the "Markdown Faces" link at the bottom of the mode
182 ;; customization screen.
184 ;;; Usage:
186 ;; Keybindings are grouped by prefixes based on their function. For
187 ;; example, commands dealing with headers begin with `C-c C-t`. The
188 ;; primary commands in each group will are described below. You can
189 ;; obtain a list of all keybindings by pressing `C-c C-h`.
191 ;; * Anchors: `C-c C-a`
193 ;; `C-c C-a l` inserts inline links of the form `[text](url)`.
194 ;; `C-c C-a r` inserts reference links of the form `[text][label]`.
195 ;; The label definition will be placed at the end of the current
196 ;; block. `C-c C-a w` acts similarly for wiki links of the form
197 ;; `[[WikiLink]]`. In all cases, if there is an active region, the
198 ;; text in the region is used as the link text.
200 ;; * Commands: `C-c C-c`
202 ;; `C-c C-c m` will run Markdown on the current buffer and preview
203 ;; the output in another buffer while `C-c C-c p` runs Markdown on
204 ;; the current buffer and previews the output in a browser.
205 ;; `C-c C-c e` will run Markdown on the current buffer and save
206 ;; the result in the file `basename.html`, where `basename` is the
207 ;; name of the Markdown file with the extension removed. **This
208 ;; file will be overwritten without notice.** Press `C-c C-c v`
209 ;; to view the exported file in a browser.
211 ;; `C-c C-c c` will check for undefined references. If there are
212 ;; any, a small buffer will open with a list of undefined
213 ;; references and the line numbers on which they appear. In Emacs
214 ;; 22 and greater, selecting a reference from this list and
215 ;; pressing `RET` will insert an empty reference definition at the
216 ;; end of the buffer. Similarly, selecting the line number will
217 ;; jump to the corresponding line.
219 ;; * Images: `C-c C-i`
221 ;; `C-c C-i i` inserts an image, using the active region (if any)
222 ;; as the alt text.
224 ;; * Physical styles: `C-c C-p`
226 ;; These commands all act on text in the active region, if any,
227 ;; and insert empty markup fragments otherwise. `C-c C-p b` makes
228 ;; the selected text bold, `C-c C-p f` formats the region as
229 ;; fixed-width text, and `C-c C-p i` is used for italic text.
231 ;; * Logical styles: `C-c C-s`
233 ;; These commands all act on text in the active region, if any,
234 ;; and insert empty markup fragments otherwise. Logical styles
235 ;; include blockquote (`C-c C-s b`), preformatted (`C-c C-s p`),
236 ;; code (`C-c C-s c`), emphasis (`C-c C-s e`), and strong
237 ;; (`C-c C-s s`).
239 ;; * Headers: `C-c C-t`
241 ;; All header commands use text in the active region, if any, as
242 ;; the header text. To insert an atx or hash style level-n
243 ;; header, press `C-c C-t n` where n is between 1 and 6. For a
244 ;; top-level setext or underline style header press `C-c C-t t`
245 ;; (mnemonic: title) and for a second-level underline-style header
246 ;; press `C-c C-t s` (mnemonic: section).
248 ;; * Footnotes: `C-c C-f`
250 ;; To create a new footnote at the point, press `C-c C-f n`.
251 ;; Press `C-c C-f g` with the point at a footnote to jump to the
252 ;; location where the footnote text is defined. Then, press
253 ;; `C-c C-f b` to return to the footnote marker in the main text.
254 ;; When the point is at a footnote marker or in the body of a
255 ;; footnote, press `C-c C-f k` to kill the footnote and add the
256 ;; text to the kill ring.
258 ;; * Other elements:
260 ;; `C-c -` inserts a horizontal rule.
262 ;; * Wiki-Link Navigation:
264 ;; Use `M-p` and `M-n` to quickly jump to the previous and next
265 ;; wiki links, respectively.
267 ;; * Outline Navigation:
269 ;; Navigation between headings is possible using `outline-mode'.
270 ;; Use `C-M-n` and `C-M-p` to move between the next and previous
271 ;; visible headings. Similarly, `C-M-f` and `C-M-b` move to the
272 ;; next and previous visible headings at the same level as the one
273 ;; at the point. Finally, `C-M-u` will move up to a lower-level
274 ;; (more inclusive) visible heading.
276 ;; Many of the commands described above behave differently depending on
277 ;; whether Transient Mark mode is enabled or not. When it makes sense,
278 ;; if Transient Mark mode is on and a region is active, the command
279 ;; applies to the text in the region (e.g., `C-c C-p b` makes the region
280 ;; bold). For users who prefer to work outside of Transient Mark mode,
281 ;; in Emacs 22 it can be enabled temporarily by pressing `C-SPC C-SPC`.
283 ;; When applicable, commands that specifically act on the region even
284 ;; outside of Transient Mark mode have the same keybinding as the with
285 ;; the exception of an additional `C-` prefix. For example,
286 ;; `markdown-insert-blockquote' is bound to `C-c C-s b` and only acts on
287 ;; the region in Transient Mark mode while `markdown-blockquote-region'
288 ;; is bound to `C-c C-s C-b` and always applies to the region (when
289 ;; nonempty).
291 ;; markdown-mode attempts to be flexible in how it handles
292 ;; indentation. When you press `TAB` repeatedly, the point will cycle
293 ;; through several possible indentation levels corresponding to things
294 ;; you might have in mind when you press `RET` at the end of a line or
295 ;; `TAB`. For example, you may want to start a new list item,
296 ;; continue a list item with hanging indentation, indent for a nested
297 ;; pre block, and so on.
299 ;; markdown-mode supports outline-minor-mode as well as org-mode-style
300 ;; visibility cycling for atx- or hash-style headers. There are two
301 ;; types of visibility cycling: Pressing `S-TAB` cycles globally between
302 ;; the table of contents view (headers only), outline view (top-level
303 ;; headers only), and the full document view. Pressing `TAB` while the
304 ;; point is at a header will cycle through levels of visibility for the
305 ;; subtree: completely folded, visible children, and fully visible.
306 ;; Note that mixing hash and underline style headers will give undesired
307 ;; results.
309 ;;; Extensions:
311 ;; Besides supporting the basic Markdown syntax, markdown-mode also
312 ;; includes syntax highlighting for `[[Wiki Links]]` by default. Wiki
313 ;; links may be followed automatically by hitting the enter key when
314 ;; your curser is on a wiki link or by hitting `C-c C-w`. The
315 ;; autofollowing on enter key may be controlled with the
316 ;; `markdown-follow-wiki-link-on-enter' customization. Use `M-p` and
317 ;; `M-n` to quickly jump to the previous and next wiki links,
318 ;; respectively. Aliased or piped wiki links of the form
319 ;; `[[link text|PageName]]` are also supported. Since some wikis
320 ;; reverse these components, set `markdown-wiki-link-alias-first'
321 ;; to nil to treat them as `[[PageName|link text]]`.
323 ;; [SmartyPants][] support is possible by customizing `markdown-command'.
324 ;; If you install `SmartyPants.pl` at, say, `/usr/local/bin/smartypants`,
325 ;; then you can set `markdown-command' to `"markdown | smartypants"`.
326 ;; You can do this either by using `M-x customize-group markdown`
327 ;; or by placing the following in your `.emacs` file:
329 ;; (defun markdown-custom ()
330 ;; "markdown-mode-hook"
331 ;; (setq markdown-command "markdown | smartypants"))
332 ;; (add-hook 'markdown-mode-hook '(lambda() (markdown-custom)))
334 ;; [SmartyPants]: http://daringfireball.net/projects/smartypants/
336 ;; Experimental syntax highlighting for mathematical expressions written
337 ;; in LaTeX (only expressions denoted by `$..$`, `$$..$$`, or `\[..\]`)
338 ;; can be enabled by setting `markdown-enable-math' to a non-nil value,
339 ;; either via customize or by placing `(setq markdown-enable-itex t)`
340 ;; in `.emacs`, and restarting Emacs.
342 ;; A [GitHub Flavored Markdown](http://github.github.com/github-flavored-markdown/)
343 ;; mode, `gfm-mode', is also available. The GitHub implementation of
344 ;; differs slightly from standard Markdown. Most importantly, newlines are
345 ;; significant and trigger hard line breaks. As such, `gfm-mode' turns off
346 ;; `auto-fill-mode' and turns on `visual-line-mode' (or `longlines-mode' if
347 ;; `visual-line-mode' is not available). Wiki links in this mode will be
348 ;; treated as on GitHub, with hyphens replacing spaces in filenames and
349 ;; where the first letter of the filename capitalized. For example,
350 ;; `[[wiki link]]' will map to a file named `Wiki-link` with the same
351 ;; extension as the current file.
353 ;;; Acknowledgments:
355 ;; markdown-mode has benefited greatly from the efforts of the
356 ;; following people:
358 ;; * Cyril Brulebois <cyril.brulebois@enst-bretagne.fr> for Debian packaging.
359 ;; * Conal Elliott <conal@conal.net> for a font-lock regexp patch.
360 ;; * Edward O'Connor <hober0@gmail.com> for a font-lock regexp fix and
361 ;; GitHub Flavored Markdown mode (`gfm-mode').
362 ;; * Greg Bognar <greg_bognar@hms.harvard.edu> for menus and running
363 ;; `markdown' with an active region.
364 ;; * Daniel Burrows <dburrows@debian.org> for filing Debian bug #456592.
365 ;; * Peter S. Galbraith <psg@debian.org> for maintaining emacs-goodies-el.
366 ;; * Dmitry Dzhus <mail@sphinx.net.ru> for reference checking functions.
367 ;; * Bryan Kyle <bryan.kyle@gmail.com> for indentation code.
368 ;; * Ben Voui <intrigeri@boum.org> for font-lock face customizations.
369 ;; * Ankit Solanki <ankit.solanki@gmail.com> for longlines.el
370 ;; compatibility and custom CSS.
371 ;; * Hilko Bengen <bengen@debian.org> for proper XHTML output.
372 ;; * Jose A. Ortega Ruiz <jao@gnu.org> for Emacs 23 fixes.
373 ;; * Alec Resnick <alec@sproutward.org> for bug reports.
374 ;; * Joost Kremers <joostkremers@fastmail.fm> for footnote-handling
375 ;; functions and bug reports regarding indentation.
376 ;; * Peter Williams <pezra@barelyenough.org> for fill-paragraph
377 ;; enhancements.
378 ;; * George Ogata <george.ogata@gmail.com> for fixing several
379 ;; byte-compilation warnings.
380 ;; * Eric Merritt <ericbmerritt@gmail.com> for wiki link features.
381 ;; * Philippe Ivaldi <pivaldi@sfr.fr> for XHTML preview
382 ;; customizations and XHTML export.
383 ;; * Jeremiah Dodds <jeremiah.dodds@gmail.com> for supporting
384 ;; Markdown processors which do not accept input from stdin.
385 ;; * Werner Dittmann <werner.dittmann@t-online.de> for bug reports
386 ;; regarding the cl dependency and auto-fill-mode and indentation.
387 ;; * Scott Pfister <scott.pfister@gmail.com> for generalizing the space
388 ;; substitution character for mapping wiki links to filenames.
389 ;; * Marcin Kasperski <marcin.kasperski@mekk.waw.pl> for a patch to
390 ;; escape shell commands.
391 ;; * Christopher J. Madsen <cjm@cjmweb.net> for patches to fix a match
392 ;; data bug and to prefer `visual-line-mode' in `gfm-mode'.
393 ;; * Shigeru Fukaya <shigeru.fukaya@gmail.com> for better adherence to
394 ;; Emacs Lisp coding conventions.
395 ;; * Donald Curtis <dcurtis@coe.edu> for fixing the `paragraph-fill' regexp.
396 ;; * Kevin Porter <kportertx@gmail.com> for wiki link handling in `gfm-mode'.
398 ;;; Bugs:
400 ;; Although markdown-mode is developed and tested primarily using
401 ;; GNU Emacs 24, compatibility with earlier Emacsen is also a
402 ;; priority.
404 ;; If you find any bugs in markdown-mode, please construct a test case
405 ;; or a patch and email me at <jrblevin@sdf.org>.
407 ;;; History:
409 ;; markdown-mode was written and is maintained by Jason Blevins. The
410 ;; first version was released on May 24, 2007.
412 ;; * 2007-05-24: Version 1.1
413 ;; * 2007-05-25: Version 1.2
414 ;; * 2007-06-05: [Version 1.3][]
415 ;; * 2007-06-29: Version 1.4
416 ;; * 2008-05-24: [Version 1.5][]
417 ;; * 2008-06-04: [Version 1.6][]
418 ;; * 2009-10-01: [Version 1.7][]
419 ;; * 2011-08-12: [Version 1.8][]
420 ;; * 2011-08-15: [Version 1.8.1][]
422 ;; [Version 1.3]: http://jblevins.org/projects/markdown-mode/rev-1-3
423 ;; [Version 1.5]: http://jblevins.org/projects/markdown-mode/rev-1-5
424 ;; [Version 1.6]: http://jblevins.org/projects/markdown-mode/rev-1-6
425 ;; [Version 1.7]: http://jblevins.org/projects/markdown-mode/rev-1-7
426 ;; [Version 1.8]: http://jblevins.org/projects/markdown-mode/rev-1-8
427 ;; [Version 1.8.1]: http://jblevins.org/projects/markdown-mode/rev-1-8-1
430 ;;; Code:
432 (require 'easymenu)
433 (require 'outline)
434 (eval-when-compile (require 'cl))
436 ;;; Constants =================================================================
438 (defconst markdown-mode-version "1.8.1"
439 "Markdown mode version number.")
441 (defconst markdown-output-buffer-name "*markdown-output*"
442 "Name of temporary buffer for markdown command output.")
444 ;;; Customizable variables ====================================================
446 (defvar markdown-mode-hook nil
447 "Hook run when entering Markdown mode.")
449 (defgroup markdown nil
450 "Major mode for editing text files in Markdown format."
451 :prefix "markdown-"
452 :group 'wp
453 :link '(url-link "http://jblevins.org/projects/markdown-mode/"))
455 (defcustom markdown-command "markdown"
456 "Command to run markdown."
457 :group 'markdown
458 :type 'string)
460 (defcustom markdown-command-needs-filename nil
461 "Set to non-nil if `markdown-command' does not accept input from stdin.
462 Instead, it will be passed a filename as the final command-line
463 option. As a result, you will only be able to run Markdown from
464 buffers which are visiting a file."
465 :group 'markdown
466 :type 'boolean)
468 (defcustom markdown-hr-string "* * * * *"
469 "String to use for horizonal rules."
470 :group 'markdown
471 :type 'string)
473 (defcustom markdown-bold-underscore nil
474 "Use two underscores for bold instead of two asterisks."
475 :group 'markdown
476 :type 'boolean)
478 (defcustom markdown-italic-underscore nil
479 "Use underscores for italic instead of asterisks."
480 :group 'markdown
481 :type 'boolean)
483 (defcustom markdown-indent-function 'markdown-indent-line
484 "Function to use to indent."
485 :group 'markdown
486 :type 'function)
488 (defcustom markdown-indent-on-enter t
489 "Automatically indent new lines when enter key is pressed."
490 :group 'markdown
491 :type 'boolean)
493 (defcustom markdown-follow-wiki-link-on-enter t
494 "Follow wiki link at point (if any) when the enter key is pressed."
495 :group 'markdown
496 :type 'boolean)
498 (defcustom markdown-wiki-link-alias-first t
499 "When non-nil, treat aliased wiki links like [[alias text|PageName]].
500 Otherwise, they will be treated as [[PageName|alias text]]."
501 :group 'markdown
502 :type 'boolean)
504 (defcustom markdown-uri-types
505 '("acap" "cid" "data" "dav" "fax" "file" "ftp" "gopher" "http" "https"
506 "imap" "ldap" "mailto" "mid" "modem" "news" "nfs" "nntp" "pop" "prospero"
507 "rtsp" "service" "sip" "tel" "telnet" "tip" "urn" "vemmi" "wais")
508 "Link types for syntax highlighting of URIs."
509 :group 'markdown
510 :type 'list)
512 (defcustom markdown-enable-math nil
513 "Syntax highlighting for inline LaTeX expressions.
514 This will not take effect until Emacs is restarted."
515 :group 'markdown
516 :type 'boolean)
518 (defcustom markdown-css-path ""
519 "URL of CSS file to link to in the output XHTML."
520 :group 'markdown
521 :type 'string)
523 (defcustom markdown-xhtml-header-content ""
524 "Additional content to include in the XHTML <head> block."
525 :group 'markdown
526 :type 'string)
528 (defcustom markdown-xhtml-standalone-regexp
529 "^\\(\<\?xml\\|\<!DOCTYPE\\|\<html\\)"
530 "Regexp indicating whether `markdown-command' output is standalone XHTML."
531 :group 'markdown
532 :type 'regexp)
534 (defcustom markdown-link-space-sub-char
536 "Character to use instead of spaces when mapping wiki links to filenames."
537 :group 'markdown
538 :type 'string)
540 (defcustom markdown-footnote-location 'end
541 "Position where new footnotes are inserted in the document."
542 :group 'markdown
543 :type '(choice (const :tag "At the end of the document" end)
544 (const :tag "Immediately after the paragraph" immediately)
545 (const :tag "Before next header" header)))
547 ;;; Font lock =================================================================
549 (require 'font-lock)
551 (defvar markdown-italic-face 'markdown-italic-face
552 "Face name to use for italic text.")
554 (defvar markdown-bold-face 'markdown-bold-face
555 "Face name to use for bold text.")
557 (defvar markdown-header-face 'markdown-header-face
558 "Face name to use as a base for headers.")
560 (defvar markdown-header-face-1 'markdown-header-face-1
561 "Face name to use for level-1 headers.")
563 (defvar markdown-header-face-2 'markdown-header-face-2
564 "Face name to use for level-2 headers.")
566 (defvar markdown-header-face-3 'markdown-header-face-3
567 "Face name to use for level-3 headers.")
569 (defvar markdown-header-face-4 'markdown-header-face-4
570 "Face name to use for level-4 headers.")
572 (defvar markdown-header-face-5 'markdown-header-face-5
573 "Face name to use for level-5 headers.")
575 (defvar markdown-header-face-6 'markdown-header-face-6
576 "Face name to use for level-6 headers.")
578 (defvar markdown-inline-code-face 'markdown-inline-code-face
579 "Face name to use for inline code.")
581 (defvar markdown-list-face 'markdown-list-face
582 "Face name to use for list markers.")
584 (defvar markdown-blockquote-face 'markdown-blockquote-face
585 "Face name to use for blockquote.")
587 (defvar markdown-pre-face 'markdown-pre-face
588 "Face name to use for preformatted text.")
590 (defvar markdown-link-face 'markdown-link-face
591 "Face name to use for links.")
593 (defvar markdown-missing-link-face 'markdown-missing-link-face
594 "Face name to use for links where the linked file does not exist.")
596 (defvar markdown-reference-face 'markdown-reference-face
597 "Face name to use for reference.")
599 (defvar markdown-footnote-face 'markdown-footnote-face
600 "Face name to use for footnote identifiers.")
602 (defvar markdown-url-face 'markdown-url-face
603 "Face name to use for URLs.")
605 (defvar markdown-link-title-face 'markdown-link-title-face
606 "Face name to use for reference link titles.")
608 (defvar markdown-comment-face 'markdown-comment-face
609 "Face name to use for HTML comments.")
611 (defvar markdown-math-face 'markdown-math-face
612 "Face name to use for LaTeX expressions.")
614 (defgroup markdown-faces nil
615 "Faces used in Markdown Mode"
616 :group 'markdown
617 :group 'faces)
619 (defface markdown-italic-face
620 '((t (:inherit font-lock-variable-name-face :slant italic)))
621 "Face for italic text."
622 :group 'markdown-faces)
624 (defface markdown-bold-face
625 '((t (:inherit font-lock-variable-name-face :weight bold)))
626 "Face for bold text."
627 :group 'markdown-faces)
629 (defface markdown-header-face
630 '((t (:inherit font-lock-function-name-face :weight bold)))
631 "Base face for headers."
632 :group 'markdown-faces)
634 (defface markdown-header-face-1
635 '((t (:inherit markdown-header-face)))
636 "Face for level-1 headers."
637 :group 'markdown-faces)
639 (defface markdown-header-face-2
640 '((t (:inherit markdown-header-face)))
641 "Face for level-2 headers."
642 :group 'markdown-faces)
644 (defface markdown-header-face-3
645 '((t (:inherit markdown-header-face)))
646 "Face for level-3 headers."
647 :group 'markdown-faces)
649 (defface markdown-header-face-4
650 '((t (:inherit markdown-header-face)))
651 "Face for level-4 headers."
652 :group 'markdown-faces)
654 (defface markdown-header-face-5
655 '((t (:inherit markdown-header-face)))
656 "Face for level-5 headers."
657 :group 'markdown-faces)
659 (defface markdown-header-face-6
660 '((t (:inherit markdown-header-face)))
661 "Face for level-6 headers."
662 :group 'markdown-faces)
664 (defface markdown-inline-code-face
665 '((t (:inherit font-lock-constant-face)))
666 "Face for inline code."
667 :group 'markdown-faces)
669 (defface markdown-list-face
670 '((t (:inherit font-lock-builtin-face)))
671 "Face for list item markers."
672 :group 'markdown-faces)
674 (defface markdown-blockquote-face
675 '((t (:inherit font-lock-doc-face)))
676 "Face for blockquote sections."
677 :group 'markdown-faces)
679 (defface markdown-pre-face
680 '((t (:inherit font-lock-constant-face)))
681 "Face for preformatted text."
682 :group 'markdown-faces)
684 (defface markdown-link-face
685 '((t (:inherit font-lock-keyword-face)))
686 "Face for links."
687 :group 'markdown-faces)
689 (defface markdown-missing-link-face
690 '((t (:inherit font-lock-warning-face)))
691 "Face for missing links."
692 :group 'markdown-faces)
694 (defface markdown-reference-face
695 '((t (:inherit font-lock-type-face)))
696 "Face for link references."
697 :group 'markdown-faces)
699 (defface markdown-footnote-face
700 '((t (:inherit font-lock-keyword-face)))
701 "Face for footnote markers."
702 :group 'markdown-faces)
704 (defface markdown-url-face
705 '((t (:inherit font-lock-string-face)))
706 "Face for URLs."
707 :group 'markdown-faces)
709 (defface markdown-link-title-face
710 '((t (:inherit font-lock-comment-face)))
711 "Face for reference link titles."
712 :group 'markdown-faces)
714 (defface markdown-comment-face
715 '((t (:inherit font-lock-comment-face)))
716 "Face for HTML comments."
717 :group 'markdown-faces)
719 (defface markdown-math-face
720 '((t (:inherit font-lock-string-face)))
721 "Face for LaTeX expressions."
722 :group 'markdown-faces)
724 (defconst markdown-regex-link-inline
725 "\\(!?\\[[^]]*?\\]\\)\\(([^\\)]*)\\)"
726 "Regular expression for a [text](file) or an image link ![text](file).")
728 (defconst markdown-regex-link-reference
729 "\\(!?\\[[^]]+?\\]\\)[ ]?\\(\\[[^]]*?\\]\\)"
730 "Regular expression for a reference link [text][id].")
732 (defconst markdown-regex-reference-definition
733 "^ \\{0,3\\}\\(\\[.*\\]\\):\\s *\\(.*?\\)\\s *\\( \"[^\"]*\"$\\|$\\)"
734 "Regular expression for a link definition [id]: ...")
736 (defconst markdown-regex-footnote
737 "\\(\\[\\^.+?\\]\\)"
738 "Regular expression for a footnote marker [^fn].")
740 (defconst markdown-regex-header
741 "#+\\|\\S-.*\n\\(?:\\(===+\\)\\|\\(---+\\)\\)$"
742 "Regexp identifying Markdown headers.")
744 (defconst markdown-regex-header-1-atx
745 "^\\(# \\)\\(.*?\\)\\($\\| #+$\\)"
746 "Regular expression for level 1 atx-style (hash mark) headers.")
748 (defconst markdown-regex-header-2-atx
749 "^\\(## \\)\\(.*?\\)\\($\\| #+$\\)"
750 "Regular expression for level 2 atx-style (hash mark) headers.")
752 (defconst markdown-regex-header-3-atx
753 "^\\(### \\)\\(.*?\\)\\($\\| #+$\\)"
754 "Regular expression for level 3 atx-style (hash mark) headers.")
756 (defconst markdown-regex-header-4-atx
757 "^\\(#### \\)\\(.*?\\)\\($\\| #+$\\)"
758 "Regular expression for level 4 atx-style (hash mark) headers.")
760 (defconst markdown-regex-header-5-atx
761 "^\\(##### \\)\\(.*?\\)\\($\\| #+$\\)"
762 "Regular expression for level 5 atx-style (hash mark) headers.")
764 (defconst markdown-regex-header-6-atx
765 "^\\(###### \\)\\(.*?\\)\\($\\| #+$\\)"
766 "Regular expression for level 6 atx-style (hash mark) headers.")
768 (defconst markdown-regex-header-1-setext
769 "^\\(.*\\)\n\\(===+\\)$"
770 "Regular expression for level 1 setext-style (underline) headers.")
772 (defconst markdown-regex-header-2-setext
773 "^\\(.*\\)\n\\(---+\\)$"
774 "Regular expression for level 2 setext-style (underline) headers.")
776 (defconst markdown-regex-hr
777 "^\\(\\*[ ]?\\*[ ]?\\*[ ]?[\\* ]*\\|-[ ]?-[ ]?-[--- ]*\\)$"
778 "Regular expression for matching Markdown horizontal rules.")
780 (defconst markdown-regex-code
781 "\\(^\\|[^\\]\\)\\(\\(`\\{1,2\\}\\)\\([^ \\]\\|[^ ]\\(.\\|\n[^\n]\\)*?[^ \\]\\)\\3\\)"
782 "Regular expression for matching inline code fragments.")
784 (defconst markdown-regex-pre
785 "^\\( \\|\t\\).*$"
786 "Regular expression for matching preformatted text sections.")
788 (defconst markdown-regex-list
789 "^[ \t]*\\([0-9]+\\.\\|[\\*\\+-]\\) "
790 "Regular expression for matching list markers.")
792 (defconst markdown-regex-bold
793 "\\(^\\|[^\\]\\)\\(\\([*_]\\{2\\}\\)\\(.\\|\n[^\n]\\)*?[^\\ ]\\3\\)"
794 "Regular expression for matching bold text.")
796 (defconst markdown-regex-italic
797 "\\(^\\|[^\\]\\)\\(\\([*_]\\)\\([^ \\]\\3\\|[^ ]\\(.\\|\n[^\n]\\)*?[^\\ ]\\3\\)\\)"
798 "Regular expression for matching italic text.")
800 (defconst markdown-regex-blockquote
801 "^>.*$"
802 "Regular expression for matching blockquote lines.")
804 (defconst markdown-regex-line-break
805 " $"
806 "Regular expression for matching line breaks.")
808 (defconst markdown-regex-wiki-link
809 "\\[\\[\\([^]|]+\\)\\(|\\([^]]+\\)\\)?\\]\\]"
810 "Regular expression for matching wiki links.
811 This matches typical bracketed [[WikiLinks]] as well as 'aliased'
812 wiki links of the form [[PageName|link text]]. In this regular
813 expression, #1 matches the page name and #3 matches the link
814 text.")
816 (defconst markdown-regex-uri
817 (concat
818 "\\(" (mapconcat 'identity markdown-uri-types "\\|")
819 "\\):[^]\t\n\r<>,;() ]+")
820 "Regular expression for matching inline URIs.")
822 (defconst markdown-regex-angle-uri
823 (concat
824 "\\(<\\)\\("
825 (mapconcat 'identity markdown-uri-types "\\|")
826 "\\):[^]\t\n\r<>,;()]+\\(>\\)")
827 "Regular expression for matching inline URIs in angle brackets.")
829 (defconst markdown-regex-email
830 "<\\(\\sw\\|\\s_\\|\\s.\\)+@\\(\\sw\\|\\s_\\|\\s.\\)+>"
831 "Regular expression for matching inline email addresses.")
833 (defconst markdown-regex-latex-expression
834 "\\(^\\|[^\\]\\)\\(\\$\\($\\([^\\$]\\|\\\\.\\)*\\$\\|\\([^\\$]\\|\\\\.\\)*\\)\\$\\)"
835 "Regular expression for itex $..$ or $$..$$ math mode expressions.")
837 (defconst markdown-regex-latex-display
838 "^\\\\\\[\\(.\\|\n\\)*?\\\\\\]$"
839 "Regular expression for itex \[..\] display mode expressions.")
841 (defconst markdown-regex-list-indent
842 "^\\(\\s *\\)\\([0-9]+\\.\\|[\\*\\+-]\\)\\(\\s +\\)"
843 "Regular expression for matching indentation of list items.")
845 (defvar markdown-mode-font-lock-keywords-basic
846 (list
847 '(markdown-match-pre-blocks 0 markdown-pre-face t t)
848 '(markdown-match-fenced-code-blocks 0 markdown-pre-face t t)
849 (cons markdown-regex-blockquote 'markdown-blockquote-face)
850 (cons markdown-regex-header-1-setext 'markdown-header-face-1)
851 (cons markdown-regex-header-2-setext 'markdown-header-face-2)
852 (cons markdown-regex-header-1-atx 'markdown-header-face-1)
853 (cons markdown-regex-header-2-atx 'markdown-header-face-2)
854 (cons markdown-regex-header-3-atx 'markdown-header-face-3)
855 (cons markdown-regex-header-4-atx 'markdown-header-face-4)
856 (cons markdown-regex-header-5-atx 'markdown-header-face-5)
857 (cons markdown-regex-header-6-atx 'markdown-header-face-6)
858 (cons markdown-regex-hr 'markdown-header-face)
859 '(markdown-match-comments 0 markdown-comment-face t t)
860 (cons markdown-regex-code '(2 markdown-inline-code-face))
861 (cons markdown-regex-angle-uri 'markdown-link-face)
862 (cons markdown-regex-uri 'markdown-link-face)
863 (cons markdown-regex-email 'markdown-link-face)
864 (cons markdown-regex-list 'markdown-list-face)
865 (cons markdown-regex-link-inline
866 '((1 markdown-link-face t)
867 (2 markdown-url-face t)))
868 (cons markdown-regex-link-reference
869 '((1 markdown-link-face t)
870 (2 markdown-reference-face t)))
871 (cons markdown-regex-reference-definition
872 '((1 markdown-reference-face t)
873 (2 markdown-url-face t)
874 (3 markdown-link-title-face t)))
875 (cons markdown-regex-footnote 'markdown-footnote-face)
876 (cons markdown-regex-bold '(2 markdown-bold-face))
877 (cons markdown-regex-italic '(2 markdown-italic-face))
879 "Syntax highlighting for Markdown files.")
881 (defconst markdown-mode-font-lock-keywords-latex
882 (list
883 ;; Math mode $..$ or $$..$$
884 (cons markdown-regex-latex-expression '(2 markdown-math-face))
885 ;; Display mode equations with brackets: \[ \]
886 (cons markdown-regex-latex-display 'markdown-math-face)
887 ;; Equation reference (eq:foo)
888 (cons "(eq:\\w+)" 'markdown-reference-face)
889 ;; Equation reference \eqref{foo}
890 (cons "\\\\eqref{\\w+}" 'markdown-reference-face))
891 "Syntax highlighting for LaTeX fragments.")
893 (defvar markdown-mode-font-lock-keywords
894 (append
895 (if markdown-enable-math
896 markdown-mode-font-lock-keywords-latex)
897 markdown-mode-font-lock-keywords-basic)
898 "Default highlighting expressions for Markdown mode.")
900 ;; Footnotes
901 (defvar markdown-footnote-counter 0
902 "Counter for footnote numbers.")
903 (make-variable-buffer-local 'markdown-footnote-counter)
905 (defconst markdown-footnote-chars
906 "[[:alnum:]-]"
907 "Regular expression maching any character that is allowed in a footnote identifier.")
911 ;;; Compatibility =============================================================
913 ;; Handle replace-regexp-in-string in XEmacs 21
914 (defun markdown-replace-regexp-in-string (regexp rep string)
915 "Compatibility wrapper to provide `replace-regexp-in-string'."
916 (if (featurep 'xemacs)
917 (replace-in-string string regexp rep)
918 (replace-regexp-in-string regexp rep string)))
922 ;;; Markdown parsing functions ================================================
924 (defun markdown-cur-line-blank-p ()
925 "Return t if the current line is blank and nil otherwise."
926 (save-excursion
927 (beginning-of-line)
928 (re-search-forward "^\\s *$" (point-at-eol) t)))
930 (defun markdown-prev-line-blank-p ()
931 "Return t if the previous line is blank and nil otherwise.
932 If we are at the first line, then consider the previous line to be blank."
933 (save-excursion
934 (if (= (point-at-bol) (point-min))
936 (forward-line -1)
937 (markdown-cur-line-blank-p))))
939 (defun markdown-next-line-blank-p ()
940 "Return t if the next line is blank and nil otherwise.
941 If we are at the last line, then consider the next line to be blank."
942 (save-excursion
943 (if (= (point-at-bol) (point-max))
945 (forward-line 1)
946 (markdown-cur-line-blank-p))))
948 (defun markdown-prev-line-indent-p ()
949 "Return t if the previous line is indented and nil otherwise."
950 (save-excursion
951 (forward-line -1)
952 (goto-char (point-at-bol))
953 (if (re-search-forward "^\\s " (point-at-eol) t) t)))
955 (defun markdown-cur-line-indent ()
956 "Return the number of leading whitespace characters in the current line."
957 (save-excursion
958 (goto-char (point-at-bol))
959 (re-search-forward "^\\s +" (point-at-eol) t)
960 (current-column)))
962 (defun markdown-prev-line-indent ()
963 "Return the number of leading whitespace characters in the previous line."
964 (save-excursion
965 (forward-line -1)
966 (markdown-cur-line-indent)))
968 (defun markdown-next-line-indent ()
969 "Return the number of leading whitespace characters in the next line."
970 (save-excursion
971 (forward-line 1)
972 (markdown-cur-line-indent)))
974 (defun markdown-cur-non-list-indent ()
975 "Return the number of leading whitespace characters in the current line."
976 (save-excursion
977 (beginning-of-line)
978 (when (re-search-forward markdown-regex-list-indent (point-at-eol) t)
979 (current-column))))
981 (defun markdown-prev-non-list-indent ()
982 "Return position of the first non-list-marker on the previous line."
983 (save-excursion
984 (forward-line -1)
985 (markdown-cur-non-list-indent)))
987 (defun markdown--next-block ()
988 "Move the point to the start of the next text block."
989 (forward-line)
990 (while (and (or (not (markdown-prev-line-blank-p))
991 (markdown-cur-line-blank-p))
992 (not (eobp)))
993 (forward-line)))
995 (defun markdown--end-of-level (level)
996 "Move the point to the end of region with indentation at least LEVEL."
997 (let (indent)
998 (while (and (not (< (setq indent (markdown-cur-line-indent)) level))
999 (not (>= indent (+ level 4)))
1000 (not (eobp)))
1001 (markdown--next-block))
1002 (unless (eobp)
1003 ;; Move back before any trailing blank lines
1004 (while (and (markdown-prev-line-blank-p)
1005 (not (bobp)))
1006 (forward-line -1))
1007 (forward-line -1)
1008 (end-of-line))))
1010 ; From html-helper-mode
1011 (defun markdown-match-comments (last)
1012 "Match HTML comments from the point to LAST."
1013 (cond ((search-forward "<!--" last t)
1014 (backward-char 4)
1015 (let ((beg (point)))
1016 (cond ((search-forward-regexp "--[ \t]*>" last t)
1017 (set-match-data (list beg (point)))
1019 (t nil))))
1020 (t nil)))
1022 (defun markdown-match-pre-blocks (last)
1023 "Match Markdown pre blocks from point to LAST.
1024 A region matches as if it is indented at least four spaces
1025 relative to the nearest previous block of lesser non-list-marker
1026 indentation."
1028 (let (cur-begin cur-end cur-indent prev-indent prev-list stop match found)
1029 ;; Don't start in the middle of a block
1030 (unless (and (bolp)
1031 (markdown-prev-line-blank-p)
1032 (not (markdown-cur-line-blank-p)))
1033 (markdown--next-block))
1035 ;; Move to the first full block in the region with indent 4 or more
1036 (while (and (not (>= (setq cur-indent (markdown-cur-line-indent)) 4))
1037 (not (>= (point) last)))
1038 (markdown--next-block))
1039 (setq cur-begin (point))
1040 (markdown--end-of-level cur-indent)
1041 (setq cur-end (point))
1042 (setq match nil)
1043 (setq stop (> cur-begin cur-end))
1045 (while (and (<= cur-end last) (not stop) (not match))
1046 ;; Move to the nearest preceding block of lesser (non-marker) indentation
1047 (setq prev-indent (+ cur-indent 1))
1048 (goto-char cur-begin)
1049 (setq found nil)
1050 (while (and (>= prev-indent cur-indent)
1051 (not (and prev-list
1052 (eq prev-indent cur-indent)))
1053 (not (bobp)))
1055 ;; Move point to the last line of the previous block.
1056 (forward-line -1)
1057 (while (and (markdown-cur-line-blank-p)
1058 (not (bobp)))
1059 (forward-line -1))
1061 ;; Update the indentation level using either the
1062 ;; non-list-marker indentation, if the previous line is the
1063 ;; start of a list, or the actual indentation.
1064 (setq prev-list (markdown-cur-non-list-indent))
1065 (setq prev-indent (or prev-list
1066 (markdown-cur-line-indent)))
1067 (setq found t))
1069 ;; If the loop didn't execute
1070 (unless found
1071 (setq prev-indent 0))
1073 ;; Compare with prev-indent minus its remainder mod 4
1074 (setq prev-indent (- prev-indent (mod prev-indent 4)))
1076 ;; Set match data and return t if we have a match
1077 (if (>= cur-indent (+ prev-indent 4))
1078 ;; Match
1079 (progn
1080 (setq match t)
1081 (set-match-data (list cur-begin cur-end))
1082 ;; Leave point at end of block
1083 (goto-char cur-end)
1084 (forward-line))
1086 ;; Move to the next block (if possible)
1087 (goto-char cur-end)
1088 (markdown--next-block)
1089 (setq cur-begin (point))
1090 (setq cur-indent (markdown-cur-line-indent))
1091 (markdown--end-of-level cur-indent)
1092 (setq cur-end (point))
1093 (setq stop (equal cur-begin cur-end))))
1094 match))
1096 (defun markdown-match-fenced-code-blocks (last)
1097 "Match fenced code blocks from the point to LAST."
1098 (cond ((search-forward-regexp "^\\([~]\\{3,\\}\\)" last t)
1099 (beginning-of-line)
1100 (let ((beg (point)))
1101 (forward-line)
1102 (cond ((search-forward-regexp
1103 (concat "^" (match-string 1) "~*") last t)
1104 (set-match-data (list beg (point)))
1106 (t nil))))
1107 (t nil)))
1109 (defun markdown-font-lock-extend-region ()
1110 "Extend the search region to include an entire block of text.
1111 This helps improve font locking for block constructs such as pre blocks."
1112 ;; Avoid compiler warnings about these global variables from font-lock.el.
1113 ;; See the documentation for variable `font-lock-extend-region-functions'.
1114 (eval-when-compile (defvar font-lock-beg) (defvar font-lock-end))
1115 (save-excursion
1116 (goto-char font-lock-beg)
1117 (let ((found (re-search-backward "\n\n" nil t)))
1118 (when found
1119 (goto-char font-lock-end)
1120 (when (re-search-forward "\n\n" nil t)
1121 (beginning-of-line)
1122 (setq font-lock-end (point)))
1123 (setq font-lock-beg found)))))
1127 ;;; Syntax Table ==============================================================
1129 (defvar markdown-mode-syntax-table
1130 (let ((markdown-mode-syntax-table (make-syntax-table)))
1131 (modify-syntax-entry ?\" "w" markdown-mode-syntax-table)
1132 markdown-mode-syntax-table)
1133 "Syntax table for `markdown-mode'.")
1137 ;;; Element Insertion =========================================================
1139 (defun markdown-wrap-or-insert (s1 s2)
1140 "Insert the strings S1 and S2.
1141 If Transient Mark mode is on and a region is active, wrap the strings S1
1142 and S2 around the region."
1143 (if (and transient-mark-mode mark-active)
1144 (let ((a (region-beginning)) (b (region-end)))
1145 (goto-char a)
1146 (insert s1)
1147 (goto-char (+ b (length s1)))
1148 (insert s2))
1149 (insert s1 s2)))
1151 (defun markdown-insert-hr ()
1152 "Insert a horizonal rule using `markdown-hr-string'."
1153 (interactive)
1154 ;; Leading blank line
1155 (when (and (>= (point) (+ (point-min) 2))
1156 (not (looking-back "\n\n" 2)))
1157 (insert "\n"))
1158 ;; Insert custom HR string
1159 (insert (concat markdown-hr-string "\n"))
1160 ;; Following blank line
1161 (backward-char)
1162 (unless (looking-at "\n\n")
1163 (insert "\n")))
1165 (defun markdown-insert-bold ()
1166 "Insert markup for a bold word or phrase.
1167 If Transient Mark mode is on and a region is active, it is made bold."
1168 (interactive)
1169 (if markdown-bold-underscore
1170 (markdown-wrap-or-insert "__" "__")
1171 (markdown-wrap-or-insert "**" "**"))
1172 (backward-char 2))
1174 (defun markdown-insert-italic ()
1175 "Insert markup for an italic word or phrase.
1176 If Transient Mark mode is on and a region is active, it is made italic."
1177 (interactive)
1178 (if markdown-italic-underscore
1179 (markdown-wrap-or-insert "_" "_")
1180 (markdown-wrap-or-insert "*" "*"))
1181 (backward-char 1))
1183 (defun markdown-insert-code ()
1184 "Insert markup for an inline code fragment.
1185 If Transient Mark mode is on and a region is active, it is marked
1186 as inline code."
1187 (interactive)
1188 (markdown-wrap-or-insert "`" "`")
1189 (backward-char 1))
1191 (defun markdown-insert-link ()
1192 "Insert an inline link of the form []().
1193 If Transient Mark mode is on and a region is active, it is used
1194 as the link text."
1195 (interactive)
1196 (markdown-wrap-or-insert "[" "]")
1197 (insert "()")
1198 (backward-char 1))
1200 (defun markdown-insert-reference-link-dwim ()
1201 "Insert a reference link of the form [text][label] at point.
1202 If Transient Mark mode is on and a region is active, the region
1203 is used as the link text. Otherwise, the link text will be read
1204 from the minibuffer. The link URL, label, and title will be read
1205 from the minibuffer. The link label definition is placed at the
1206 end of the current paragraph."
1207 (interactive)
1208 (if (and transient-mark-mode mark-active)
1209 (call-interactively 'markdown-insert-reference-link-region)
1210 (call-interactively 'markdown-insert-reference-link)))
1212 (defun markdown-insert-reference-link-region (url label title)
1213 "Insert a reference link at point using the region as the link text."
1214 (interactive "sLink URL: \nsLink Label (optional): \nsLink Title (optional): ")
1215 (let ((text (buffer-substring (region-beginning) (region-end))))
1216 (delete-region (region-beginning) (region-end))
1217 (markdown-insert-reference-link text url label title)))
1219 (defun markdown-insert-reference-link (text url label title)
1220 "Insert a reference link at point.
1221 The link label definition is placed at the end of the current
1222 paragraph."
1223 (interactive "sLink Text: \nsLink URL: \nsLink Label (optional): \nsLink Title (optional): ")
1224 (let (end)
1225 (insert (concat "[" text "][" label "]"))
1226 (setq end (point))
1227 (forward-paragraph)
1228 (insert "\n[")
1229 (if (> (length label) 0)
1230 (insert label)
1231 (insert text))
1232 (insert (concat "]: " url))
1233 (unless (> (length url) 0)
1234 (setq end (point)))
1235 (when (> (length title) 0)
1236 (insert (concat " \"" title "\"")))
1237 (insert "\n")
1238 (unless (looking-at "\n")
1239 (insert "\n"))
1240 (goto-char end)))
1242 (defun markdown-insert-wiki-link ()
1243 "Insert a wiki link of the form [[WikiLink]].
1244 If Transient Mark mode is on and a region is active, it is used
1245 as the link text."
1246 (interactive)
1247 (markdown-wrap-or-insert "[[" "]]")
1248 (backward-char 2))
1250 (defun markdown-insert-image ()
1251 "Insert an inline image tag of the form ![]().
1252 If Transient Mark mode is on and a region is active, it is used
1253 as the alt text of the image."
1254 (interactive)
1255 (markdown-wrap-or-insert "![" "]")
1256 (insert "()")
1257 (backward-char 1))
1259 (defun markdown-insert-header-1 ()
1260 "Insert a first level atx-style (hash mark) header.
1261 If Transient Mark mode is on and a region is active, it is used
1262 as the header text."
1263 (interactive)
1264 (markdown-insert-header 1))
1266 (defun markdown-insert-header-2 ()
1267 "Insert a second level atx-style (hash mark) header.
1268 If Transient Mark mode is on and a region is active, it is used
1269 as the header text."
1270 (interactive)
1271 (markdown-insert-header 2))
1273 (defun markdown-insert-header-3 ()
1274 "Insert a third level atx-style (hash mark) header.
1275 If Transient Mark mode is on and a region is active, it is used
1276 as the header text."
1277 (interactive)
1278 (markdown-insert-header 3))
1280 (defun markdown-insert-header-4 ()
1281 "Insert a fourth level atx-style (hash mark) header.
1282 If Transient Mark mode is on and a region is active, it is used
1283 as the header text."
1284 (interactive)
1285 (markdown-insert-header 4))
1287 (defun markdown-insert-header-5 ()
1288 "Insert a fifth level atx-style (hash mark) header.
1289 If Transient Mark mode is on and a region is active, it is used
1290 as the header text."
1291 (interactive)
1292 (markdown-insert-header 5))
1294 (defun markdown-insert-header-6 ()
1295 "Insert a sixth level atx-style (hash mark) header.
1296 If Transient Mark mode is on and a region is active, it is used
1297 as the header text."
1298 (interactive)
1299 (markdown-insert-header 6))
1301 (defun markdown-insert-header (n)
1302 "Insert an atx-style (hash mark) header.
1303 With no prefix argument, insert a level-1 header. With prefix N,
1304 insert a level-N header. If Transient Mark mode is on and the
1305 region is active, it is used as the header text."
1306 (interactive "p")
1307 (unless n ; Test to see if n is defined
1308 (setq n 1)) ; Default to level 1 header
1309 (let (hdr hdrl hdrr)
1310 (dotimes (count n hdr)
1311 (setq hdr (concat "#" hdr))) ; Build a hash mark header string
1312 (setq hdrl (concat hdr " "))
1313 (setq hdrr (concat " " hdr))
1314 (markdown-wrap-or-insert hdrl hdrr))
1315 (backward-char (+ 1 n)))
1317 (defun markdown-insert-title ()
1318 "Insert a setext-style (underline) first level header.
1319 If Transient Mark mode is on and a region is active, it is used
1320 as the header text."
1321 (interactive)
1322 (if (and transient-mark-mode mark-active)
1323 (let ((a (region-beginning))
1324 (b (region-end))
1325 (len 0)
1326 (hdr))
1327 (setq len (- b a))
1328 (dotimes (count len hdr)
1329 (setq hdr (concat "=" hdr))) ; Build a === title underline
1330 (end-of-line)
1331 (insert "\n" hdr "\n"))
1332 (insert "\n==========\n")
1333 (backward-char 12)))
1335 (defun markdown-insert-section ()
1336 "Insert a setext-style (underline) second level header.
1337 If Transient Mark mode is on and a region is active, it is used
1338 as the header text."
1339 (interactive)
1340 (if (and transient-mark-mode mark-active)
1341 (let ((a (region-beginning))
1342 (b (region-end))
1343 (len 0)
1344 (hdr))
1345 (setq len (- b a))
1346 (dotimes (count len hdr)
1347 (setq hdr (concat "-" hdr))) ; Build a --- section underline
1348 (end-of-line)
1349 (insert "\n" hdr "\n"))
1350 (insert "\n----------\n")
1351 (backward-char 12)))
1353 (defun markdown-insert-blockquote ()
1354 "Start a blockquote section (or blockquote the region).
1355 If Transient Mark mode is on and a region is active, it is used as
1356 the blockquote text."
1357 (interactive)
1358 (if (and (boundp 'transient-mark-mode) transient-mark-mode mark-active)
1359 (markdown-blockquote-region (region-beginning) (region-end))
1360 (insert "> ")))
1362 (defun markdown-block-region (beg end prefix)
1363 "Format the region using a block prefix.
1364 Arguments BEG and END specify the beginning and end of the
1365 region. The characters PREFIX will appear at the beginning
1366 of each line."
1367 (if mark-active
1368 (save-excursion
1369 ;; Ensure that there is a leading blank line
1370 (goto-char beg)
1371 (when (and (>= (point) (+ (point-min) 2))
1372 (not (looking-back "\n\n" 2)))
1373 (insert "\n")
1374 (setq beg (1+ beg))
1375 (setq end (1+ end)))
1376 ;; Move back before any blank lines at the end
1377 (goto-char end)
1378 (while (and (looking-back "\n" 1)
1379 (not (equal (point) (point-min))))
1380 (backward-char)
1381 (setq end (1- end)))
1382 ;; Ensure that there is a trailing blank line
1383 (goto-char end)
1384 (if (not (or (looking-at "\n\n")
1385 (and (equal (1+ end) (point-max)) (looking-at "\n"))))
1386 (insert "\n"))
1387 ;; Insert PREFIX
1388 (goto-char beg)
1389 (beginning-of-line)
1390 (while (< (point-at-bol) end)
1391 (insert prefix)
1392 (setq end (+ (length prefix) end))
1393 (forward-line)))))
1395 (defun markdown-blockquote-region (beg end)
1396 "Blockquote the region.
1397 Arguments BEG and END specify the beginning and end of the region."
1398 (interactive "*r")
1399 (markdown-block-region beg end "> "))
1401 (defun markdown-insert-pre ()
1402 "Start a preformatted section (or apply to the region).
1403 If Transient Mark mode is on and a region is active, it is marked
1404 as preformatted text."
1405 (interactive)
1406 (if (and (boundp 'transient-mark-mode) transient-mark-mode mark-active)
1407 (markdown-pre-region (region-beginning) (region-end))
1408 (insert " ")))
1410 (defun markdown-pre-region (beg end)
1411 "Format the region as preformatted text.
1412 Arguments BEG and END specify the beginning and end of the region."
1413 (interactive "*r")
1414 (markdown-block-region beg end " "))
1416 ;;; Footnotes ======================================================================
1418 (defun markdown-footnote-counter-inc ()
1419 "Increment markdown-footnote-counter and return the new value."
1420 (when (= markdown-footnote-counter 0) ; hasn't been updated in this buffer yet.
1421 (save-excursion
1422 (goto-char (point-min))
1423 (while (re-search-forward (concat "^\\[\\^\\(" markdown-footnote-chars "*?\\)\\]:")
1424 (point-max) t)
1425 (let ((fn (string-to-number (match-string 1))))
1426 (when (> fn markdown-footnote-counter)
1427 (setq markdown-footnote-counter fn))))))
1428 (incf markdown-footnote-counter))
1430 (defun markdown-footnote-new ()
1431 "Insert a footnote with a new number and jump to a position to enter the
1432 footnote text."
1433 (interactive)
1434 (let ((fn (markdown-footnote-counter-inc)))
1435 (insert (format "[^%d]" fn))
1436 (markdown-footnote-text-find-new-location)
1437 (insert (format "[^%d]: " fn))))
1439 (defun markdown-footnote-text-find-new-location ()
1440 "Position the cursor at the proper location for a new footnote text."
1441 (cond
1442 ((eq markdown-footnote-location 'end) (goto-char (point-max)))
1443 ((eq markdown-footnote-location 'immediately) (forward-paragraph))
1444 ((eq markdown-footnote-location 'header)
1445 ;; search for a header. if none is found, go to the end of the document.
1446 (catch 'eof
1447 (while (progn
1448 (forward-paragraph)
1449 (unless (re-search-forward markdown-regex-header nil t)
1450 (throw 'eof nil))
1451 (backward-paragraph)
1452 (not (looking-at (concat "\n" markdown-regex-header))))))))
1453 ;; make sure we're on an empty line:
1454 (unless (markdown-cur-line-blank-p)
1455 (insert "\n"))
1456 ;; and make sure the previous line is empty:
1457 (unless (markdown-prev-line-blank-p)
1458 (insert "\n"))
1459 ;; then make sure there's an empty line following the footnote:
1460 (unless (markdown-next-line-blank-p)
1461 (insert "\n")
1462 (forward-line -1)))
1464 (defun markdown-footnote-kill ()
1465 "Kill the footnote at point.
1466 The footnote text is killed (and added to the kill ring), the
1467 footnote marker is deleted. Point has to be either at the
1468 footnote marker or in the footnote text."
1469 (interactive)
1470 (let (return-pos)
1471 (when (markdown-footnote-text-positions) ; if we're in a footnote text
1472 (markdown-footnote-return) ; we first move to the marker
1473 (setq return-pos 'text)) ; and remember our return position
1474 (let ((marker (markdown-footnote-delete-marker)))
1475 (unless marker
1476 (error "Not at a footnote"))
1477 (let ((text-pos (markdown-footnote-find-text (car marker))))
1478 (unless text-pos
1479 (error "No text for footnote `%s'" (car marker)))
1480 (goto-char text-pos)
1481 (let ((pos (markdown-footnote-kill-text)))
1482 (setq return-pos
1483 (if (and pos (eq return-pos 'text))
1485 (cadr marker))))))
1486 (goto-char return-pos)))
1488 (defun markdown-footnote-delete-marker ()
1489 "Delete a footnote marker at point.
1490 Returns a list (ID START) containing the footnote ID and the
1491 start position of the marker before deletion. If no footnote
1492 marker was deleted, this function returns NIL."
1493 (let ((marker (markdown-footnote-marker-positions)))
1494 (when marker
1495 (delete-region (second marker) (third marker))
1496 (butlast marker))))
1498 (defun markdown-footnote-kill-text ()
1499 "Kill footnote text at point.
1500 Returns the start position of the footnote text before deletion,
1501 or NIL if point was not inside a footnote text.
1503 The killed text is placed in the kill ring (without the footnote
1504 number)."
1505 (let ((fn (markdown-footnote-text-positions)))
1506 (when fn
1507 (let ((text (delete-and-extract-region (second fn) (third fn))))
1508 (string-match (concat "\\[\\" (first fn) "\\]:[[:space:]]*\\(\\(.*\n?\\)*\\)") text)
1509 (kill-new (match-string 1 text))
1510 (second fn)))))
1512 (defun markdown-footnote-goto-text ()
1513 "Jump to the text of the footnote at point."
1514 (interactive)
1515 (let ((fn (car (markdown-footnote-marker-positions))))
1516 (unless fn
1517 (error "Not at a footnote marker"))
1518 (let ((new-pos (markdown-footnote-find-text fn)))
1519 (unless new-pos
1520 (error "No definition found for footnote `%s'" fn))
1521 (goto-char new-pos))))
1523 (defun markdown-footnote-return ()
1524 "Return from a footnote to its footnote number in the main text."
1525 (interactive)
1526 (let ((fn (save-excursion
1527 (car (markdown-footnote-text-positions)))))
1528 (unless fn
1529 (error "Not in a footnote"))
1530 (let ((new-pos (markdown-footnote-find-marker fn)))
1531 (unless new-pos
1532 (error "Footnote marker `%s' not found" fn))
1533 (goto-char new-pos))))
1535 (defun markdown-footnote-find-marker (id)
1536 "Find the location of the footnote marker with ID.
1537 The actual buffer position returned is the position directly
1538 following the marker's closing bracket. If no marker is found,
1539 NIL is returned."
1540 (save-excursion
1541 (goto-char (point-min))
1542 (when (re-search-forward (concat "\\[" id "\\]\\([^:]\\|\\'\\)") nil t)
1543 (skip-chars-backward "^]")
1544 (point))))
1546 (defun markdown-footnote-find-text (id)
1547 "Find the location of the text of footnote ID.
1548 The actual buffer position returned is the position of the first
1549 character of the text, after the footnote's identifier. If no
1550 footnote text is found, NIL is returned."
1551 (save-excursion
1552 (goto-char (point-min))
1553 (when (re-search-forward (concat "^\\[" id "\\]:") nil t)
1554 (skip-chars-forward "[:space:]")
1555 (point))))
1557 (defun markdown-footnote-marker-positions ()
1558 "Return the position and ID of the footnote marker point is on.
1559 The return value is a list (ID START END). If point is not on a
1560 footnote, NIL is returned."
1561 ;; first make sure we're at a footnote marker
1562 (if (or (looking-back (concat "\\[\\^" markdown-footnote-chars "*\\]?") (point-at-bol))
1563 (looking-at (concat "\\[?\\^" markdown-footnote-chars "*?\\]")))
1564 (save-excursion
1565 ;; move point between [ and ^:
1566 (if (looking-at "\\[")
1567 (forward-char 1)
1568 (skip-chars-backward "^["))
1569 (looking-at (concat "\\(\\^" markdown-footnote-chars "*?\\)\\]"))
1570 (list (match-string 1) (1- (match-beginning 1)) (1+ (match-end 1))))))
1572 (defun markdown-footnote-text-positions ()
1573 "Return the start and end positions of the footnote text point is in.
1574 The exact return value is a list of three elements: (ID START
1575 END). The start position is the position of the opening bracket
1576 of the footnote id. The end position is directly after the
1577 newline that ends the footnote. If point is not in a footnote,
1578 NIL is returned instead."
1579 (save-excursion
1580 (let ((fn (progn
1581 (backward-paragraph)
1582 ;; if we're in a multiparagraph footnote, we need to back up further
1583 (while (>= (markdown-next-line-indent) 4)
1584 (backward-paragraph))
1585 (forward-line)
1586 (if (looking-at (concat "^\\[\\(\\^" markdown-footnote-chars "*?\\)\\]:"))
1587 (list (match-string 1) (point))))))
1588 (when fn
1589 (while (progn
1590 (forward-paragraph)
1591 (>= (markdown-next-line-indent) 4)))
1592 (append fn (list (point)))))))
1594 ;;; Indentation ====================================================================
1596 (defun markdown-indent-find-next-position (cur-pos positions)
1597 "Return the position after the index of CUR-POS in POSITIONS."
1598 (while (and positions
1599 (not (equal cur-pos (car positions))))
1600 (setq positions (cdr positions)))
1601 (or (cadr positions) 0))
1603 (defun markdown-indent-line ()
1604 "Indent the current line using some heuristics.
1605 If the _previous_ command was either `markdown-enter-key' or
1606 `markdown-cycle', then we should cycle to the next
1607 reasonable indentation position. Otherwise, we could have been
1608 called directly by `markdown-enter-key', by an initial call of
1609 `markdown-cycle', or indirectly by `auto-fill-mode'. In
1610 these cases, indent to the default position."
1611 (interactive)
1612 (let ((positions (markdown-calc-indents))
1613 (cur-pos (current-column)))
1614 (if (not (equal this-command 'markdown-cycle))
1615 (indent-line-to (car positions))
1616 (setq positions (sort (delete-dups positions) '<))
1617 (indent-line-to
1618 (markdown-indent-find-next-position cur-pos positions)))))
1620 (defun markdown-calc-indents ()
1621 "Return a list of indentation columns to cycle through.
1622 The first element in the returned list should be considered the
1623 default indentation level."
1624 (let (pos prev-line-pos positions)
1626 ;; Previous line indent
1627 (setq prev-line-pos (markdown-prev-line-indent))
1628 (setq positions (cons prev-line-pos positions))
1630 ;; Previous non-list-marker indent
1631 (setq pos (markdown-prev-non-list-indent))
1632 (when pos
1633 (setq positions (cons pos positions))
1634 (setq positions (cons (+ pos tab-width) positions)))
1636 ;; Indentation of the previous line + tab-width
1637 (cond
1638 (prev-line-pos
1639 (setq positions (cons (+ prev-line-pos tab-width) positions)))
1641 (setq positions (cons tab-width positions))))
1643 ;; Indentation of the previous line - tab-width
1644 (if (and prev-line-pos
1645 (> prev-line-pos tab-width))
1646 (setq positions (cons (- prev-line-pos tab-width) positions)))
1648 ;; Indentation of preceeding list item
1649 (setq pos
1650 (save-excursion
1651 (forward-line -1)
1652 (catch 'break
1653 (while (not (equal (point) (point-min)))
1654 (forward-line -1)
1655 (goto-char (point-at-bol))
1656 (when (re-search-forward markdown-regex-list-indent (point-at-eol) t)
1657 (throw 'break (length (match-string 1)))))
1658 nil)))
1659 (if (and pos (not (eq pos prev-line-pos)))
1660 (setq positions (cons pos positions)))
1662 ;; First column
1663 (setq positions (cons 0 positions))
1665 (reverse positions)))
1667 (defun markdown-do-normal-return ()
1668 "Insert a newline and optionally indent the next line."
1669 (newline)
1670 (if markdown-indent-on-enter
1671 (funcall indent-line-function)))
1673 (defun markdown-enter-key ()
1674 "Handle RET according to context.
1675 If there is a wiki link at the point, follow it unless
1676 `markdown-follow-wiki-link-on-enter' is nil. Otherwise, process
1677 it in the usual way."
1678 (interactive)
1679 (if (and markdown-follow-wiki-link-on-enter (markdown-wiki-link-p))
1680 (markdown-follow-wiki-link-at-point)
1681 (markdown-do-normal-return)))
1685 ;;; Keymap ====================================================================
1687 (defvar markdown-mode-map
1688 (let ((map (make-keymap)))
1689 ;; Element insertion
1690 (define-key map "\C-c\C-al" 'markdown-insert-link)
1691 (define-key map "\C-c\C-ar" 'markdown-insert-reference-link-dwim)
1692 (define-key map "\C-c\C-aw" 'markdown-insert-wiki-link)
1693 (define-key map "\C-c\C-ii" 'markdown-insert-image)
1694 (define-key map "\C-c\C-t1" 'markdown-insert-header-1)
1695 (define-key map "\C-c\C-t2" 'markdown-insert-header-2)
1696 (define-key map "\C-c\C-t3" 'markdown-insert-header-3)
1697 (define-key map "\C-c\C-t4" 'markdown-insert-header-4)
1698 (define-key map "\C-c\C-t5" 'markdown-insert-header-5)
1699 (define-key map "\C-c\C-t6" 'markdown-insert-header-6)
1700 (define-key map "\C-c\C-pb" 'markdown-insert-bold)
1701 (define-key map "\C-c\C-ss" 'markdown-insert-bold)
1702 (define-key map "\C-c\C-pi" 'markdown-insert-italic)
1703 (define-key map "\C-c\C-se" 'markdown-insert-italic)
1704 (define-key map "\C-c\C-pf" 'markdown-insert-code)
1705 (define-key map "\C-c\C-sc" 'markdown-insert-code)
1706 (define-key map "\C-c\C-sb" 'markdown-insert-blockquote)
1707 (define-key map "\C-c\C-s\C-b" 'markdown-blockquote-region)
1708 (define-key map "\C-c\C-sp" 'markdown-insert-pre)
1709 (define-key map "\C-c\C-s\C-p" 'markdown-pre-region)
1710 (define-key map "\C-c-" 'markdown-insert-hr)
1711 (define-key map "\C-c\C-tt" 'markdown-insert-title)
1712 (define-key map "\C-c\C-ts" 'markdown-insert-section)
1713 ;; Footnotes
1714 (define-key map "\C-c\C-fn" 'markdown-footnote-new)
1715 (define-key map "\C-c\C-fg" 'markdown-footnote-goto-text)
1716 (define-key map "\C-c\C-fb" 'markdown-footnote-return)
1717 (define-key map "\C-c\C-fk" 'markdown-footnote-kill)
1718 ;; WikiLink Following
1719 (define-key map "\C-c\C-w" 'markdown-follow-wiki-link-at-point)
1720 (define-key map "\M-n" 'markdown-next-wiki-link)
1721 (define-key map "\M-p" 'markdown-previous-wiki-link)
1722 ;; Indentation
1723 (define-key map "\C-m" 'markdown-enter-key)
1724 ;; Visibility cycling
1725 (define-key map (kbd "<tab>") 'markdown-cycle)
1726 (define-key map (kbd "<S-iso-lefttab>") 'markdown-shifttab)
1727 ;; Header navigation
1728 (define-key map (kbd "C-M-n") 'outline-next-visible-heading)
1729 (define-key map (kbd "C-M-p") 'outline-previous-visible-heading)
1730 (define-key map (kbd "C-M-f") 'outline-forward-same-level)
1731 (define-key map (kbd "C-M-b") 'outline-backward-same-level)
1732 (define-key map (kbd "C-M-u") 'outline-up-heading)
1733 ;; Markdown functions
1734 (define-key map "\C-c\C-cm" 'markdown)
1735 (define-key map "\C-c\C-cp" 'markdown-preview)
1736 (define-key map "\C-c\C-ce" 'markdown-export)
1737 (define-key map "\C-c\C-cv" 'markdown-export-and-view)
1738 ;; References
1739 (define-key map "\C-c\C-cc" 'markdown-check-refs)
1740 map)
1741 "Keymap for Markdown major mode.")
1743 ;;; Menu ==================================================================
1745 (easy-menu-define markdown-mode-menu markdown-mode-map
1746 "Menu for Markdown mode"
1747 '("Markdown"
1748 ("Show/Hide"
1749 ["Cycle visibility" markdown-cycle (outline-on-heading-p)]
1750 ["Cycle global visibility" markdown-shifttab])
1751 "---"
1752 ["Compile" markdown]
1753 ["Preview" markdown-preview]
1754 ["Export" markdown-export]
1755 ["Export & View" markdown-export-and-view]
1756 "---"
1757 ("Headers (setext)"
1758 ["Insert Title" markdown-insert-title]
1759 ["Insert Section" markdown-insert-section])
1760 ("Headers (atx)"
1761 ["First level" markdown-insert-header-1]
1762 ["Second level" markdown-insert-header-2]
1763 ["Third level" markdown-insert-header-3]
1764 ["Fourth level" markdown-insert-header-4]
1765 ["Fifth level" markdown-insert-header-5]
1766 ["Sixth level" markdown-insert-header-6])
1767 "---"
1768 ["Bold" markdown-insert-bold]
1769 ["Italic" markdown-insert-italic]
1770 ["Blockquote" markdown-insert-blockquote]
1771 ["Preformatted" markdown-insert-pre]
1772 ["Code" markdown-insert-code]
1773 "---"
1774 ["Insert inline link" markdown-insert-link]
1775 ["Insert reference link" markdown-insert-reference-link-dwim]
1776 ["Insert image" markdown-insert-image]
1777 ["Insert horizontal rule" markdown-insert-hr]
1778 "---"
1779 ("Footnotes"
1780 ["Insert footnote" markdown-footnote-new]
1781 ["Jump to footnote text" markdown-footnote-goto-text]
1782 ["Return from footnote" markdown-footnote-return])
1783 "---"
1784 ["Check references" markdown-check-refs]
1785 "---"
1786 ["Version" markdown-show-version]
1791 ;;; References ================================================================
1793 ;;; Undefined reference checking code by Dmitry Dzhus <mail@sphinx.net.ru>.
1795 (defconst markdown-refcheck-buffer
1796 "*Undefined references for %buffer%*"
1797 "Pattern for name of buffer for listing undefined references.
1798 The string %buffer% will be replaced by the corresponding
1799 `markdown-mode' buffer name.")
1801 (defun markdown-has-reference-definition (reference)
1802 "Find out whether Markdown REFERENCE is defined.
1804 REFERENCE should include the square brackets, like [this]."
1805 (let ((reference (downcase reference)))
1806 (save-excursion
1807 (goto-char (point-min))
1808 (catch 'found
1809 (while (re-search-forward markdown-regex-reference-definition nil t)
1810 (when (string= reference (downcase (match-string-no-properties 1)))
1811 (throw 'found t)))))))
1813 (defun markdown-get-undefined-refs ()
1814 "Return a list of undefined Markdown references.
1816 Result is an alist of pairs (reference . occurencies), where
1817 occurencies is itself another alist of pairs (label .
1818 line-number).
1820 For example, an alist corresponding to [Nice editor][Emacs] at line 12,
1821 \[GNU Emacs][Emacs] at line 45 and [manual][elisp] at line 127 is
1822 \((\"[emacs]\" (\"[Nice editor]\" . 12) (\"[GNU Emacs]\" . 45)) (\"[elisp]\" (\"[manual]\" . 127)))."
1823 (let ((missing))
1824 (save-excursion
1825 (goto-char (point-min))
1826 (while
1827 (re-search-forward markdown-regex-link-reference nil t)
1828 (let* ((label (match-string-no-properties 1))
1829 (reference (match-string-no-properties 2))
1830 (target (downcase (if (string= reference "[]") label reference))))
1831 (unless (markdown-has-reference-definition target)
1832 (let ((entry (assoc target missing)))
1833 (if (not entry)
1834 (add-to-list 'missing (cons target
1835 (list (cons label (markdown-line-number-at-pos)))) t)
1836 (setcdr entry
1837 (append (cdr entry) (list (cons label (markdown-line-number-at-pos))))))))))
1838 missing)))
1840 (defun markdown-add-missing-ref-definition (ref buffer &optional recheck)
1841 "Add blank REF definition to the end of BUFFER.
1843 REF is a Markdown reference in square brackets, like \"[lisp-history]\".
1845 When RECHECK is non-nil, BUFFER gets rechecked for undefined
1846 references so that REF disappears from the list of those links."
1847 (with-current-buffer buffer
1848 (when (not (eq major-mode 'markdown-mode))
1849 (error "Not available in current mode"))
1850 (goto-char (point-max))
1851 (indent-new-comment-line)
1852 (insert (concat ref ": ")))
1853 (switch-to-buffer-other-window buffer)
1854 (goto-char (point-max))
1855 (when recheck
1856 (markdown-check-refs t)))
1858 ;; Button which adds an empty Markdown reference definition to the end
1859 ;; of buffer specified as its 'target-buffer property. Reference name
1860 ;; is button's label
1861 (when (>= emacs-major-version 22)
1862 (define-button-type 'markdown-ref-button
1863 'help-echo "Push to create an empty reference definition"
1864 'face 'bold
1865 'action (lambda (b)
1866 (markdown-add-missing-ref-definition
1867 (button-label b) (button-get b 'target-buffer) t))))
1869 ;; Button jumping to line in buffer specified as its 'target-buffer
1870 ;; property. Line number is button's 'line property.
1871 (when (>= emacs-major-version 22)
1872 (define-button-type 'goto-line-button
1873 'help-echo "Push to go to this line"
1874 'face 'italic
1875 'action (lambda (b)
1876 (message (button-get b 'buffer))
1877 (switch-to-buffer-other-window (button-get b 'target-buffer))
1878 ;; use call-interactively to silence compiler
1879 (call-interactively 'goto-line (button-get b 'target-line)))))
1881 (defun markdown-check-refs (&optional silent)
1882 "Show all undefined Markdown references in current `markdown-mode' buffer.
1884 If SILENT is non-nil, do not message anything when no undefined
1885 references found.
1887 Links which have empty reference definitions are considered to be
1888 defined."
1889 (interactive "P")
1890 (when (not (eq major-mode 'markdown-mode))
1891 (error "Not available in current mode"))
1892 (let ((oldbuf (current-buffer))
1893 (refs (markdown-get-undefined-refs))
1894 (refbuf (get-buffer-create (markdown-replace-regexp-in-string
1895 "%buffer%" (buffer-name)
1896 markdown-refcheck-buffer))))
1897 (if (null refs)
1898 (progn
1899 (when (not silent)
1900 (message "No undefined references found"))
1901 (kill-buffer refbuf))
1902 (with-current-buffer refbuf
1903 (when view-mode
1904 (View-exit-and-edit))
1905 (erase-buffer)
1906 (insert "Following references lack definitions:")
1907 (newline 2)
1908 (dolist (ref refs)
1909 (let ((button-label (format "%s" (car ref))))
1910 (if (>= emacs-major-version 22)
1911 ;; Create a reference button in Emacs 22
1912 (insert-text-button button-label
1913 :type 'markdown-ref-button
1914 'target-buffer oldbuf)
1915 ;; Insert reference as text in Emacs < 22
1916 (insert button-label)))
1917 (insert " (")
1918 (dolist (occurency (cdr ref))
1919 (let ((line (cdr occurency)))
1920 (if (>= emacs-major-version 22)
1921 ;; Create a line number button in Emacs 22
1922 (insert-button (number-to-string line)
1923 :type 'goto-line-button
1924 'target-buffer oldbuf
1925 'target-line line)
1926 ;; Insert line number as text in Emacs < 22
1927 (insert (number-to-string line)))
1928 (insert " "))) (delete-char -1)
1929 (insert ")")
1930 (newline))
1931 (view-buffer-other-window refbuf)
1932 (goto-char (point-min))
1933 (forward-line 2)))))
1935 ;;; Outline ===================================================================
1937 ;; The following visibility cycling code was taken from org-mode
1938 ;; by Carsten Dominik and adapted for markdown-mode.
1940 (defvar markdown-cycle-global-status 1)
1941 (defvar markdown-cycle-subtree-status nil)
1943 ;; Based on org-end-of-subtree from org.el
1944 (defun markdown-end-of-subtree (&optional invisible-OK)
1945 "Move to the end of the current subtree.
1946 Only visible heading lines are considered, unless INVISIBLE-OK is
1947 non-nil."
1948 (outline-back-to-heading invisible-OK)
1949 (let ((first t)
1950 (level (funcall outline-level)))
1951 (while (and (not (eobp))
1952 (or first (> (funcall outline-level) level)))
1953 (setq first nil)
1954 (outline-next-heading))
1955 (if (memq (preceding-char) '(?\n ?\^M))
1956 (progn
1957 ;; Go to end of line before heading
1958 (forward-char -1)
1959 (if (memq (preceding-char) '(?\n ?\^M))
1960 ;; leave blank line before heading
1961 (forward-char -1)))))
1962 (point))
1964 ;; Based on org-cycle from org.el.
1965 (defun markdown-cycle (&optional arg)
1966 "Visibility cycling for Markdown mode.
1967 If ARG is t, perform global visibility cycling. If the point is
1968 at an atx-style header, cycle visibility of the corresponding
1969 subtree. Otherwise, insert a tab using `indent-relative'."
1970 (interactive "P")
1971 (cond
1972 ((eq arg t) ;; Global cycling
1973 (cond
1974 ((and (eq last-command this-command)
1975 (eq markdown-cycle-global-status 2))
1976 ;; Move from overview to contents
1977 (hide-sublevels 1)
1978 (message "CONTENTS")
1979 (setq markdown-cycle-global-status 3))
1981 ((and (eq last-command this-command)
1982 (eq markdown-cycle-global-status 3))
1983 ;; Move from contents to all
1984 (show-all)
1985 (message "SHOW ALL")
1986 (setq markdown-cycle-global-status 1))
1989 ;; Defaults to overview
1990 (hide-body)
1991 (message "OVERVIEW")
1992 (setq markdown-cycle-global-status 2))))
1994 ((save-excursion (beginning-of-line 1) (looking-at outline-regexp))
1995 ;; At a heading: rotate between three different views
1996 (outline-back-to-heading)
1997 (let ((goal-column 0) eoh eol eos)
1998 ;; Determine boundaries
1999 (save-excursion
2000 (outline-back-to-heading)
2001 (save-excursion
2002 (beginning-of-line 2)
2003 (while (and (not (eobp)) ;; this is like `next-line'
2004 (get-char-property (1- (point)) 'invisible))
2005 (beginning-of-line 2)) (setq eol (point)))
2006 (outline-end-of-heading) (setq eoh (point))
2007 (markdown-end-of-subtree t)
2008 (skip-chars-forward " \t\n")
2009 (beginning-of-line 1) ; in case this is an item
2010 (setq eos (1- (point))))
2011 ;; Find out what to do next and set `this-command'
2012 (cond
2013 ((= eos eoh)
2014 ;; Nothing is hidden behind this heading
2015 (message "EMPTY ENTRY")
2016 (setq markdown-cycle-subtree-status nil))
2017 ((>= eol eos)
2018 ;; Entire subtree is hidden in one line: open it
2019 (show-entry)
2020 (show-children)
2021 (message "CHILDREN")
2022 (setq markdown-cycle-subtree-status 'children))
2023 ((and (eq last-command this-command)
2024 (eq markdown-cycle-subtree-status 'children))
2025 ;; We just showed the children, now show everything.
2026 (show-subtree)
2027 (message "SUBTREE")
2028 (setq markdown-cycle-subtree-status 'subtree))
2030 ;; Default action: hide the subtree.
2031 (hide-subtree)
2032 (message "FOLDED")
2033 (setq markdown-cycle-subtree-status 'folded)))))
2036 (indent-for-tab-command))))
2038 ;; Based on org-shifttab from org.el.
2039 (defun markdown-shifttab ()
2040 "Global visibility cycling.
2041 Calls `markdown-cycle' with argument t."
2042 (interactive)
2043 (markdown-cycle t))
2045 (defun markdown-outline-level ()
2046 "Return the depth to which a statement is nested in the outline."
2047 (cond
2048 ((match-end 1) 1)
2049 ((match-end 2) 2)
2050 ((- (match-end 0) (match-beginning 0)))))
2052 ;;; Commands ==================================================================
2054 (defun markdown (&optional output-buffer-name)
2055 "Run `markdown' on current buffer and insert output in buffer BUFFER-OUTPUT."
2056 (interactive)
2057 (let ((title (buffer-name))
2058 (begin-region)
2059 (end-region))
2060 (if (and (boundp 'transient-mark-mode) transient-mark-mode mark-active)
2061 (setq begin-region (region-beginning)
2062 end-region (region-end))
2063 (setq begin-region (point-min)
2064 end-region (point-max)))
2066 (unless output-buffer-name
2067 (setq output-buffer-name markdown-output-buffer-name))
2069 (if markdown-command-needs-filename
2070 ;; Handle case when `markdown-command' does not read from stdin
2071 (if (not buffer-file-name)
2072 (error "Must be visiting a file")
2073 (shell-command (concat markdown-command " "
2074 (shell-quote-argument buffer-file-name))
2075 output-buffer-name))
2076 ;; Pass region to `markdown-command' via stdin
2077 (shell-command-on-region begin-region end-region markdown-command
2078 output-buffer-name))
2080 ;; Add header and footer and switch to html-mode.
2081 (save-current-buffer
2082 (set-buffer output-buffer-name)
2083 (goto-char (point-min))
2084 (unless (markdown-output-standalone-p)
2085 (markdown-add-xhtml-header-and-footer title))
2086 (html-mode))
2088 ;; Ensure buffer gets raised, even with short command output
2089 (switch-to-buffer-other-window output-buffer-name)))
2091 (defun markdown-output-standalone-p ()
2092 "Determine whether `markdown-command' output is standalone XHTML.
2093 Standalone XHTML output is identified by an occurrence of
2094 `markdown-xhtml-standalone-regexp' in the first five lines of output."
2095 (re-search-forward
2096 markdown-xhtml-standalone-regexp
2097 (save-excursion (goto-char (point-min)) (forward-line 4) (point))
2100 (defun markdown-add-xhtml-header-and-footer (title)
2101 "Wrap XHTML header and footer with given TITLE around current buffer."
2102 (insert "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"
2103 "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"\n"
2104 "\t\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n\n"
2105 "<html xmlns=\"http://www.w3.org/1999/xhtml\">\n\n"
2106 "<head>\n<title>")
2107 (insert title)
2108 (insert "</title>\n")
2109 (if (> (length markdown-css-path) 0)
2110 (insert "<link rel=\"stylesheet\" type=\"text/css\" media=\"all\" href=\""
2111 markdown-css-path
2112 "\" />\n"))
2113 (when (> (length markdown-xhtml-header-content) 0)
2114 (insert markdown-xhtml-header-content))
2115 (insert "\n</head>\n\n"
2116 "<body>\n\n")
2117 (goto-char (point-max))
2118 (insert "\n"
2119 "</body>\n"
2120 "</html>\n"))
2122 (defun markdown-preview ()
2123 "Run `markdown' on the current buffer and preview the output in a browser."
2124 (interactive)
2125 (markdown markdown-output-buffer-name)
2126 (browse-url-of-buffer markdown-output-buffer-name))
2128 (defun markdown-export-file-name ()
2129 "Attempt to generate a filename for Markdown output.
2130 If the current buffer is visiting a file, we construct a new
2131 output filename based on that filename. Otherwise, return nil."
2132 (when (buffer-file-name)
2133 (concat (file-name-sans-extension (buffer-file-name)) ".html")))
2135 (defun markdown-export ()
2136 "Run Markdown on the current buffer, save to a file, and return the filename.
2137 The resulting filename will be constructed using the current filename, but
2138 with the extension removed and replaced with .html."
2139 (interactive)
2140 (let ((output-file (markdown-export-file-name))
2141 (output-buffer-name))
2142 (when output-file
2143 (setq output-buffer-name (buffer-name (find-file-noselect output-file)))
2144 (markdown output-buffer-name)
2145 (with-current-buffer output-buffer-name
2146 (save-buffer)
2147 (kill-buffer-and-window))
2148 output-file)))
2150 (defun markdown-export-and-view ()
2151 "Export to XHTML using `markdown-export' and browse the resulting file."
2152 (interactive)
2153 (browse-url (markdown-export)))
2155 ;;; WikiLink Following/Markup =================================================
2157 (require 'thingatpt)
2159 (defun markdown-wiki-link-p ()
2160 "Return non-nil when `point' is at a true wiki link.
2161 A true wiki link name matches `markdown-regex-wiki-link' but does not
2162 match the current file name after conversion. This modifies the data
2163 returned by `match-data'. Note that the potential wiki link name must
2164 be available via `match-string'."
2165 (let ((case-fold-search nil))
2166 (and (thing-at-point-looking-at markdown-regex-wiki-link)
2167 (or (not buffer-file-name)
2168 (not (string-equal (buffer-file-name)
2169 (markdown-convert-wiki-link-to-filename
2170 (markdown-wiki-link-link)))))
2171 (not (save-match-data
2172 (save-excursion))))))
2174 (defun markdown-wiki-link-link ()
2175 "Return the link part of the wiki link using current match data.
2176 The location of the link component depends on the value of
2177 `markdown-wiki-link-alias-first'."
2178 (if markdown-wiki-link-alias-first
2179 (or (match-string 3) (match-string 1))
2180 (match-string 1)))
2182 (defun markdown-convert-wiki-link-to-filename (name)
2183 "Generate a filename from the wiki link NAME.
2184 Spaces in NAME are replaced with `markdown-link-space-sub-char'.
2185 When in `gfm-mode', follow GitHub's conventions where [[Test Test]]
2186 and [[test test]] both map to Test-test.ext."
2187 (let ((basename (markdown-replace-regexp-in-string
2188 "[[:space:]\n]" markdown-link-space-sub-char name)))
2189 (when (eq major-mode 'gfm-mode)
2190 (setq basename (concat (upcase (substring basename 0 1))
2191 (downcase (substring basename 1 nil)))))
2192 (concat basename
2193 (if (buffer-file-name)
2194 (concat "."
2195 (file-name-extension (buffer-file-name)))))))
2197 (defun markdown-follow-wiki-link (name)
2198 "Follow the wiki link NAME.
2199 Convert the name to a file name and call `find-file'. Ensure that
2200 the new buffer remains in `markdown-mode'."
2201 (let ((filename (markdown-convert-wiki-link-to-filename name)))
2202 (find-file filename))
2203 (markdown-mode))
2205 (defun markdown-follow-wiki-link-at-point ()
2206 "Find Wiki Link at point.
2207 See `markdown-wiki-link-p' and `markdown-follow-wiki-link'."
2208 (interactive)
2209 (if (markdown-wiki-link-p)
2210 (markdown-follow-wiki-link (markdown-wiki-link-link))
2211 (error "Point is not at a Wiki Link")))
2213 (defun markdown-next-wiki-link ()
2214 "Jump to next wiki link.
2215 See `markdown-wiki-link-p'."
2216 (interactive)
2217 (if (markdown-wiki-link-p)
2218 ; At a wiki link already, move past it.
2219 (goto-char (+ 1 (match-end 0))))
2220 (save-match-data
2221 ; Search for the next wiki link and move to the beginning.
2222 (re-search-forward markdown-regex-wiki-link nil t)
2223 (goto-char (match-beginning 0))))
2225 (defun markdown-previous-wiki-link ()
2226 "Jump to previous wiki link.
2227 See `markdown-wiki-link-p'."
2228 (interactive)
2229 (re-search-backward markdown-regex-wiki-link nil t))
2231 (defun markdown-highlight-wiki-link (from to face)
2232 "Highlight the wiki link in the region between FROM and TO using FACE."
2233 (put-text-property from to 'font-lock-face face))
2235 (defun markdown-unfontify-region-wiki-links (from to)
2236 "Remove wiki link faces from the region specified by FROM and TO."
2237 (interactive "nfrom: \nnto: ")
2238 (remove-text-properties from to '(font-lock-face markdown-link-face))
2239 (remove-text-properties from to '(font-lock-face markdown-missing-link-face)))
2241 (defun markdown-fontify-region-wiki-links (from to)
2242 "Search region given by FROM and TO for wiki links and fontify them.
2243 If a wiki link is found check to see if the backing file exists
2244 and highlight accordingly."
2245 (goto-char from)
2246 (while (re-search-forward markdown-regex-wiki-link to t)
2247 (let ((highlight-beginning (match-beginning 0))
2248 (highlight-end (match-end 0))
2249 (file-name
2250 (markdown-convert-wiki-link-to-filename
2251 (markdown-wiki-link-link))))
2252 (if (file-exists-p file-name)
2253 (markdown-highlight-wiki-link
2254 highlight-beginning highlight-end markdown-link-face)
2255 (markdown-highlight-wiki-link
2256 highlight-beginning highlight-end markdown-missing-link-face)))))
2258 (defun markdown-extend-changed-region (from to)
2259 "Extend region given by FROM and TO so that we can fontify all links.
2260 The region is extended to the first newline before and the first
2261 newline after."
2262 ;; start looking for the first new line before 'from
2263 (goto-char from)
2264 (re-search-backward "\n" nil t)
2265 (let ((new-from (point-min))
2266 (new-to (point-max)))
2267 (if (not (= (point) from))
2268 (setq new-from (point)))
2269 ;; do the same thing for the first new line after 'to
2270 (goto-char to)
2271 (re-search-forward "\n" nil t)
2272 (if (not (= (point) to))
2273 (setq new-to (point)))
2274 (list new-from new-to)))
2276 (defun markdown-check-change-for-wiki-link (from to change)
2277 "Check region between FROM and TO for wiki links and re-fontfy as needed.
2278 Designed to be used with the `after-change-functions' hook.
2279 CHANGE is the number of bytes of pre-change text replaced by the
2280 given range."
2281 (interactive "nfrom: \nnto: \nnchange: ")
2282 (let* ((inhibit-quit t)
2283 (modified (buffer-modified-p))
2284 (buffer-undo-list t)
2285 (inhibit-read-only t)
2286 (inhibit-point-motion-hooks t)
2287 (inhibit-modification-hooks t)
2288 (current-point (point))
2289 deactivate-mark)
2290 (unwind-protect
2291 (save-match-data
2292 (save-restriction
2293 ;; Extend the region to fontify so that it starts
2294 ;; and ends at safe places.
2295 (multiple-value-bind (new-from new-to)
2296 (markdown-extend-changed-region from to)
2297 ;; Unfontify existing fontification (start from scratch)
2298 (markdown-unfontify-region-wiki-links new-from new-to)
2299 ;; Now do the fontification.
2300 (markdown-fontify-region-wiki-links new-from new-to)))
2301 (unless modified
2302 (if (fboundp 'restore-buffer-modified-p)
2303 (restore-buffer-modified-p nil)
2304 (set-buffer-modified-p nil))))
2305 (goto-char current-point))))
2307 (defun markdown-fontify-buffer-wiki-links ()
2308 "Refontify all wiki links in the buffer."
2309 (interactive)
2310 (markdown-check-change-for-wiki-link (point-min) (point-max) 0))
2312 ;;; Miscellaneous =============================================================
2314 (defun markdown-line-number-at-pos (&optional pos)
2315 "Return (narrowed) buffer line number at position POS.
2316 If POS is nil, use current buffer location.
2317 This is an exact copy of `line-number-at-pos' for use in emacs21."
2318 (let ((opoint (or pos (point))) start)
2319 (save-excursion
2320 (goto-char (point-min))
2321 (setq start (point))
2322 (goto-char opoint)
2323 (forward-line 0)
2324 (1+ (count-lines start (point))))))
2326 (defun markdown-nobreak-p ()
2327 "Return nil if it is acceptable to break the current line at the point."
2328 ;; inside in square brackets (e.g., link anchor text)
2329 (looking-back "\\[[^]]*"))
2333 ;;; Mode definition ==========================================================
2335 (defun markdown-show-version ()
2336 "Show the version number in the minibuffer."
2337 (interactive)
2338 (message "markdown-mode, version %s" markdown-mode-version))
2340 ;;;###autoload
2341 (define-derived-mode markdown-mode text-mode "Markdown"
2342 "Major mode for editing Markdown files."
2343 ;; Natural Markdown tab width
2344 (setq tab-width 4)
2345 ;; Comments
2346 (make-local-variable 'comment-start)
2347 (setq comment-start "<!-- ")
2348 (make-local-variable 'comment-end)
2349 (setq comment-end " -->")
2350 (make-local-variable 'comment-start-skip)
2351 (setq comment-start-skip "<!--[ \t]*")
2352 (make-local-variable 'comment-column)
2353 (setq comment-column 0)
2354 ;; Font lock.
2355 (set (make-local-variable 'font-lock-defaults)
2356 '(markdown-mode-font-lock-keywords))
2357 (set (make-local-variable 'font-lock-multiline) t)
2358 ;; For menu support in XEmacs
2359 (easy-menu-add markdown-mode-menu markdown-mode-map)
2360 ;; Make filling work with lists (unordered, ordered, and definition)
2361 (set (make-local-variable 'paragraph-start)
2362 "\f\\|[ \t]*$\\|^[ \t]*[*+-] \\|^[ \t]*[0-9]+\\.\\|^[ \t]*: ")
2363 ;; Outline mode
2364 (make-local-variable 'outline-regexp)
2365 (setq outline-regexp markdown-regex-header)
2366 (make-local-variable 'outline-level)
2367 (setq outline-level 'markdown-outline-level)
2368 ;; Cause use of ellipses for invisible text.
2369 (add-to-invisibility-spec '(outline . t))
2370 ;; Indentation and filling
2371 (make-local-variable 'fill-nobreak-predicate)
2372 (add-hook 'fill-nobreak-predicate 'markdown-nobreak-p)
2373 (setq indent-line-function markdown-indent-function)
2375 ;; Prepare hooks for XEmacs compatibility
2376 (when (featurep 'xemacs)
2377 (make-local-hook 'after-change-functions)
2378 (make-local-hook 'font-lock-extend-region-functions)
2379 (make-local-hook 'window-configuration-change-hook))
2381 ;; Multiline font lock
2382 (add-hook 'font-lock-extend-region-functions
2383 'markdown-font-lock-extend-region)
2385 ;; Anytime text changes make sure it gets fontified correctly
2386 (add-hook 'after-change-functions 'markdown-check-change-for-wiki-link t t)
2388 ;; If we left the buffer there is a really good chance we were
2389 ;; creating one of the wiki link documents. Make sure we get
2390 ;; refontified when we come back.
2391 (add-hook 'window-configuration-change-hook
2392 'markdown-fontify-buffer-wiki-links t t)
2394 ;; do the initial link fontification
2395 (markdown-fontify-buffer-wiki-links))
2397 ;(add-to-list 'auto-mode-alist '("\\.text$" . markdown-mode))
2399 ;;; GitHub Flavored Markdown Mode ============================================
2401 (define-derived-mode gfm-mode markdown-mode "GFM"
2402 "Major mode for editing GitHub Flavored Markdown files."
2403 (setq markdown-link-space-sub-char "-")
2404 (auto-fill-mode 0)
2405 ;; Use visual-line-mode if available, fall back to longlines-mode:
2406 (if (fboundp 'visual-line-mode)
2407 (visual-line-mode 1)
2408 (longlines-mode 1))
2409 ;; do the initial link fontification
2410 (markdown-fontify-buffer-wiki-links))
2413 (provide 'markdown-mode)
2415 ;;; markdown-mode.el ends here