markdown-mode 1.9
[markdown-mode.git] / markdown-mode.el
blobd41b10d0e97b48808fd5e8b43894d9f1077e60dd
1 ;;; markdown-mode.el --- Emacs Major mode for Markdown-formatted text files
3 ;; Copyright (C) 2007-2013 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>
20 ;; Copyright (C) 2011-2012 Donald Ephraim Curtis <dcurtis@milkbox.net>
21 ;; Copyright (C) 2012 Akinori Musha <knu@idaemons.org>
22 ;; Copyright (C) 2012 Zhenlei Jia <zhenlei.jia@gmail.com>
23 ;; Copyright (C) 2012 Peter Jones <pjones@pmade.com>
25 ;; Author: Jason R. Blevins <jrblevin@sdf.org>
26 ;; Maintainer: Jason R. Blevins <jrblevin@sdf.org>
27 ;; Created: May 24, 2007
28 ;; Version: 1.9
29 ;; Keywords: Markdown, GitHub Flavored Markdown, itex
30 ;; URL: http://jblevins.org/projects/markdown-mode/
32 ;; This file is not part of GNU Emacs.
34 ;; This program is free software; you can redistribute it and/or modify
35 ;; it under the terms of the GNU General Public License as published by
36 ;; the Free Software Foundation; either version 2, or (at your option)
37 ;; any later version.
39 ;; This program is distributed in the hope that it will be useful,
40 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
41 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
42 ;; GNU General Public License for more details.
44 ;; You should have received a copy of the GNU General Public License
45 ;; along with this program; if not, write to the Free Software
46 ;; Foundation, Inc., 51 Franklin Street, Fifth Floor,
47 ;; Boston, MA 02110-1301, USA.
49 ;;; Commentary:
51 ;; markdown-mode is a major mode for editing [Markdown][]-formatted
52 ;; text files in GNU Emacs. markdown-mode is free software, licensed
53 ;; under the GNU GPL.
55 ;; [Markdown]: http://daringfireball.net/projects/markdown/
57 ;; The latest stable version is markdown-mode 1.9, released on January 25, 2013:
59 ;; * [markdown-mode.el][]
60 ;; * [Screenshot][]
61 ;; * [Release notes][]
63 ;; [markdown-mode.el]: http://jblevins.org/projects/markdown-mode/markdown-mode.el
64 ;; [screenshot]: http://jblevins.org/projects/markdown-mode/screenshots/20110812-001.png
65 ;; [release notes]: http://jblevins.org/projects/markdown-mode/rev-1-9
67 ;; markdown-mode is also available in several package managers, including:
69 ;; * Debian and Ubuntu Linux: [emacs-goodies-el][]
70 ;; * RedHat and Fedora Linux: [emacs-goodies][]
71 ;; * OpenBSD: [textproc/markdown-mode][]
72 ;; * Arch Linux (AUR): [emacs-markdown-mode-git][]
73 ;; * MacPorts: [markdown-mode.el][macports-package] ([pending][macports-ticket])
75 ;; [emacs-goodies-el]: http://packages.debian.org/emacs-goodies-el
76 ;; [emacs-goodies]: https://admin.fedoraproject.org/pkgdb/acls/name/emacs-goodies
77 ;; [textproc/markdown-mode]: http://pkgsrc.se/textproc/markdown-mode
78 ;; [emacs-markdown-mode-git]: http://aur.archlinux.org/packages.php?ID=30389
79 ;; [macports-package]: https://trac.macports.org/browser/trunk/dports/editors/markdown-mode.el/Portfile
80 ;; [macports-ticket]: http://trac.macports.org/ticket/35716
82 ;; The latest development version can be downloaded directly
83 ;; ([markdown-mode.el][devel.el]) or it can be obtained from the
84 ;; (browsable and clonable) Git repository at
85 ;; <http://jblevins.org/git/markdown-mode.git>. The entire repository,
86 ;; including the full project history, can be cloned via the Git protocol
87 ;; by running
89 ;; git clone git://jblevins.org/git/markdown-mode.git
91 ;; [devel.el]: http://jblevins.org/git/markdown-mode.git/plain/markdown-mode.el
93 ;;; Dependencies:
95 ;; markdown-mode requires easymenu, a standard package since GNU Emacs
96 ;; 19 and XEmacs 19, which provides a uniform interface for creating
97 ;; menus in GNU Emacs and XEmacs.
99 ;;; Installation:
101 ;; Make sure to place `markdown-mode.el` somewhere in the load-path and add
102 ;; the following lines to your `.emacs` file to associate markdown-mode
103 ;; with `.text` files:
105 ;; (autoload 'markdown-mode "markdown-mode"
106 ;; "Major mode for editing Markdown files" t)
107 ;; (add-to-list 'auto-mode-alist '("\\.text\\'" . markdown-mode))
109 ;; There is no consensus on an official file extension so change `.text` to
110 ;; `.mdwn`, `.md`, `.mdt`, or whatever you call your markdown files.
112 ;;; Customization:
114 ;; Although no configuration is *necessary* there are a few things
115 ;; that can be customized. The `M-x customize-mode` command
116 ;; provides an interface to all of the possible customizations:
118 ;; * `markdown-command' - the command used to run Markdown (default:
119 ;; `markdown'). This variable may be customized to pass
120 ;; command-line options to your Markdown processor of choice, but
121 ;; this command must accept input from `stdin`. If it does not, a
122 ;; simple wrapper script can be used to write `stdin` to a file
123 ;; and then pass that file to your Markdown interpreter. Ideally,
124 ;; this command will produce an XHTML fragment around which
125 ;; markdown-mode will wrap a header and footer (which can be
126 ;; further customized). However, it attempts to detect whether
127 ;; the command produces standalone XHTML output (via
128 ;; `markdown-xhtml-standalone-regexp'), in which case no header
129 ;; and footer content will be added.
131 ;; * `markdown-command-needs-filename' - set to non-nil if
132 ;; `markdown-command' does not accept input from stdin (default: nil).
133 ;; Instead, it will be passed a filename as the final command-line
134 ;; option. As a result, you will only be able to run Markdown
135 ;; from buffers which are visiting a file.
137 ;; * `markdown-open-command' - the command used for calling a standalone
138 ;; Markdown previewer which is capable of opening Markdown source files
139 ;; directly (default: `nil'). This command will be called
140 ;; with a single argument, the filename of the current buffer.
141 ;; A representative program is the Mac app [Marked][], a
142 ;; live-updating MultiMarkdown previewer which has a command line
143 ;; utility at `/usr/local/bin/mark`.
145 ;; * `markdown-hr-string' - string to use when inserting horizontal
146 ;; rules (default: `* * * * *').
148 ;; * `markdown-bold-underscore' - set to a non-nil value to use two
149 ;; underscores for bold instead of two asterisks (default: `nil').
151 ;; * `markdown-italic-underscore' - set to a non-nil value to use
152 ;; underscores for italic instead of asterisks (default: `nil').
154 ;; * `markdown-indent-function' - the function to use for automatic
155 ;; indentation (default: `markdown-indent-line').
157 ;; * `markdown-indent-on-enter' - set to a non-nil value to
158 ;; automatically indent new lines when the enter key is pressed
159 ;; (default: `t')
161 ;; * `markdown-follow-wiki-link-on-enter' - set to a non-nil value
162 ;; to automatically open a linked document in a new buffer if the
163 ;; cursor is an wiki link
164 ;; (default: `t')
166 ;; * `markdown-wiki-link-alias-first' - set to a non-nil value to
167 ;; treat aliased wiki links like `[[link text|PageName]]`.
168 ;; When set to nil, they will be treated as `[[PageName|link text]]'.
170 ;; * `markdown-uri-types' - a list of protocols for URIs that
171 ;; `markdown-mode' should highlight.
173 ;; * `markdown-enable-math' - syntax highlighting for
174 ;; LaTeX fragments (default: `nil').
176 ;; * `markdown-css-path' - CSS file to link to in XHTML output.
178 ;; * `markdown-content-type' - when set to a nonempty string, an
179 ;; `http-equiv` attribute will be included in the XHTML `<head>`
180 ;; block. If needed, the suggested values are
181 ;; `application/xhtml+xml` or `text/html`.
183 ;; * `markdown-coding-system' - used for specifying the character
184 ;; set identifier in the `http-equiv` attribute (see
185 ;; `markdown-content-type'). When set to `nil',
186 ;; `buffer-file-coding-system' will be used (and falling back to
187 ;; `iso-8859-1' when unavailable). Common settings are `utf-8'
188 ;; and `iso-latin-1'.
190 ;; * `markdown-xhtml-header-content' - additional content to include
191 ;; in the XHTML `<head>` block.
193 ;; * `markdown-xhtml-standalone-regexp' - a regular expression which
194 ;; indicates whether the output of `markdown-command' is standalone
195 ;; XHTML (default: `^\\(\<\?xml\\|\<!DOCTYPE\\|\<html\\)`). If
196 ;; this is not matched, we assume this output is a fragment and add
197 ;; our own header and footer.
199 ;; * `markdown-link-space-sub-char' - a character to replace spaces
200 ;; when mapping wiki links to filenames (default: `_`).
201 ;; For example, use an underscore for compatibility with the
202 ;; Python Markdown WikiLinks extension or a hyphen for compatibility
203 ;; with Github wiki links.
205 ;; Additionally, the faces used for syntax highlighting can be modified to
206 ;; your liking by issuing `M-x customize-group RET markdown-faces`
207 ;; or by using the "Markdown Faces" link at the bottom of the mode
208 ;; customization screen.
210 ;; [Marked]: https://itunes.apple.com/us/app/marked/id448925439?ls=1&mt=12&partnerId=30&siteID=GpHp3Acs1Yo
212 ;;; Usage:
214 ;; Keybindings are grouped by prefixes based on their function. For
215 ;; example, commands dealing with headers begin with `C-c C-t`. The
216 ;; primary commands in each group will are described below. You can
217 ;; obtain a list of all keybindings by pressing `C-c C-h`.
219 ;; * Anchors: `C-c C-a`
221 ;; `C-c C-a l` inserts inline links of the form `[text](url)`.
222 ;; `C-c C-a r` inserts reference links of the form `[text][label]`.
223 ;; The label definition will be placed at the end of the current
224 ;; block. `C-c C-a w` acts similarly for wiki links of the form
225 ;; `[[WikiLink]]`. In all cases, if there is an active region, the
226 ;; text in the region is used as the link text.
228 ;; * Commands: `C-c C-c`
230 ;; *Compile:* `C-c C-c m` will run Markdown on the current buffer
231 ;; and show the output in another buffer. *Preview*: `C-c C-c p`
232 ;; runs Markdown on the current buffer and previews, stores the
233 ;; output in a temporary file, and displays the file in a browser.
234 ;; *Export:* `C-c C-c e` will run Markdown on the current buffer
235 ;; and save the result in the file `basename.html`, where
236 ;; `basename` is the name of the Markdown file with the extension
237 ;; removed. *Export and View:* press `C-c C-c v` to export the
238 ;; file and view it in a browser. **For both export commands, the
239 ;; output file will be overwritten without notice.**
240 ;; *Open:* `C-c C-c o` will open the Markdown source file directly
241 ;; using `markdown-open-command'.
243 ;; To summarize:
245 ;; - `C-c C-c m`: `markdown-command' > `*markdown-output*` buffer.
246 ;; - `C-c C-c p`: `markdown-command' > temporary file > browser.
247 ;; - `C-c C-c e`: `markdown-command' > `basename.html`.
248 ;; - `C-c C-c v`: `markdown-command' > `basename.html` > browser.
249 ;; - `C-c C-c o`: `markdown-open-command'.
251 ;; `C-c C-c c` will check for undefined references. If there are
252 ;; any, a small buffer will open with a list of undefined
253 ;; references and the line numbers on which they appear. In Emacs
254 ;; 22 and greater, selecting a reference from this list and
255 ;; pressing `RET` will insert an empty reference definition at the
256 ;; end of the buffer. Similarly, selecting the line number will
257 ;; jump to the corresponding line.
259 ;; `C-c C-c n` will clean up the numbering of ordered lists.
261 ;; * Images: `C-c C-i`
263 ;; `C-c C-i i` inserts an image, using the active region (if any)
264 ;; as the alt text.
266 ;; * Physical styles: `C-c C-p`
268 ;; These commands all act on text in the active region, if any,
269 ;; and insert empty markup fragments otherwise. `C-c C-p b` makes
270 ;; the selected text bold, `C-c C-p f` formats the region as
271 ;; fixed-width text, and `C-c C-p i` is used for italic text.
273 ;; * Logical styles: `C-c C-s`
275 ;; These commands all act on text in the active region, if any,
276 ;; and insert empty markup fragments otherwise. Logical styles
277 ;; include blockquote (`C-c C-s b`), preformatted (`C-c C-s p`),
278 ;; code (`C-c C-s c`), emphasis (`C-c C-s e`), and strong
279 ;; (`C-c C-s s`).
281 ;; * Headers: `C-c C-t`
283 ;; All header commands use text in the active region, if any, as
284 ;; the header text. To insert an atx or hash style level-n
285 ;; header, press `C-c C-t n` where n is between 1 and 6. For a
286 ;; top-level setext or underline style header press `C-c C-t t`
287 ;; (mnemonic: title) and for a second-level underline-style header
288 ;; press `C-c C-t s` (mnemonic: section).
290 ;; * Footnotes: `C-c C-f`
292 ;; To create a new footnote at the point, press `C-c C-f n`.
293 ;; Press `C-c C-f g` with the point at a footnote to jump to the
294 ;; location where the footnote text is defined. Then, press
295 ;; `C-c C-f b` to return to the footnote marker in the main text.
296 ;; When the point is at a footnote marker or in the body of a
297 ;; footnote, press `C-c C-f k` to kill the footnote and add the
298 ;; text to the kill ring.
300 ;; * Other elements:
302 ;; `C-c -` inserts a horizontal rule.
304 ;; * Links:
306 ;; Press `C-c C-o` when the point is on an inline or reference
307 ;; link to open the URL in a browser.
309 ;; * Wiki-Link Navigation:
311 ;; Use `M-p` and `M-n` to quickly jump to the previous and next
312 ;; wiki links, respectively.
314 ;; * Outline Navigation:
316 ;; Navigation between headings is possible using `outline-mode'.
317 ;; Use `C-M-n` and `C-M-p` to move between the next and previous
318 ;; visible headings. Similarly, `C-M-f` and `C-M-b` move to the
319 ;; next and previous visible headings at the same level as the one
320 ;; at the point. Finally, `C-M-u` will move up to a lower-level
321 ;; (more inclusive) visible heading.
323 ;; Many of the commands described above behave differently depending on
324 ;; whether Transient Mark mode is enabled or not. When it makes sense,
325 ;; if Transient Mark mode is on and a region is active, the command
326 ;; applies to the text in the region (e.g., `C-c C-p b` makes the region
327 ;; bold). For users who prefer to work outside of Transient Mark mode,
328 ;; in Emacs 22 it can be enabled temporarily by pressing `C-SPC C-SPC`.
330 ;; When applicable, commands that specifically act on the region even
331 ;; outside of Transient Mark mode have the same keybinding as the with
332 ;; the exception of an additional `C-` prefix. For example,
333 ;; `markdown-insert-blockquote' is bound to `C-c C-s b` and only acts on
334 ;; the region in Transient Mark mode while `markdown-blockquote-region'
335 ;; is bound to `C-c C-s C-b` and always applies to the region (when
336 ;; nonempty).
338 ;; markdown-mode attempts to be flexible in how it handles
339 ;; indentation. When you press `TAB` repeatedly, the point will cycle
340 ;; through several possible indentation levels corresponding to things
341 ;; you might have in mind when you press `RET` at the end of a line or
342 ;; `TAB`. For example, you may want to start a new list item,
343 ;; continue a list item with hanging indentation, indent for a nested
344 ;; pre block, and so on.
346 ;; markdown-mode supports outline-minor-mode as well as org-mode-style
347 ;; visibility cycling for atx- or hash-style headers. There are two
348 ;; types of visibility cycling: Pressing `S-TAB` cycles globally between
349 ;; the table of contents view (headers only), outline view (top-level
350 ;; headers only), and the full document view. Pressing `TAB` while the
351 ;; point is at a header will cycle through levels of visibility for the
352 ;; subtree: completely folded, visible children, and fully visible.
353 ;; Note that mixing hash and underline style headers will give undesired
354 ;; results.
356 ;;; Extensions:
358 ;; Besides supporting the basic Markdown syntax, markdown-mode also
359 ;; includes syntax highlighting for `[[Wiki Links]]` by default. Wiki
360 ;; links may be followed automatically by hitting the enter key when
361 ;; your curser is on a wiki link or by hitting `C-c C-w`. The
362 ;; autofollowing on enter key may be controlled with the
363 ;; `markdown-follow-wiki-link-on-enter' customization. Use `M-p` and
364 ;; `M-n` to quickly jump to the previous and next wiki links,
365 ;; respectively. Aliased or piped wiki links of the form
366 ;; `[[link text|PageName]]` are also supported. Since some wikis
367 ;; reverse these components, set `markdown-wiki-link-alias-first'
368 ;; to nil to treat them as `[[PageName|link text]]`.
370 ;; [SmartyPants][] support is possible by customizing `markdown-command'.
371 ;; If you install `SmartyPants.pl` at, say, `/usr/local/bin/smartypants`,
372 ;; then you can set `markdown-command' to `"markdown | smartypants"`.
373 ;; You can do this either by using `M-x customize-group markdown`
374 ;; or by placing the following in your `.emacs` file:
376 ;; (defun markdown-custom ()
377 ;; "markdown-mode-hook"
378 ;; (setq markdown-command "markdown | smartypants"))
379 ;; (add-hook 'markdown-mode-hook '(lambda() (markdown-custom)))
381 ;; [SmartyPants]: http://daringfireball.net/projects/smartypants/
383 ;; Experimental syntax highlighting for mathematical expressions written
384 ;; in LaTeX (only expressions denoted by `$..$`, `$$..$$`, or `\[..\]`)
385 ;; can be enabled by setting `markdown-enable-math' to a non-nil value,
386 ;; either via customize or by placing `(setq markdown-enable-itex t)`
387 ;; in `.emacs`, and restarting Emacs.
389 ;; A [GitHub Flavored Markdown](http://github.github.com/github-flavored-markdown/)
390 ;; mode, `gfm-mode', is also available. The GitHub implementation of
391 ;; differs slightly from standard Markdown. Most importantly, newlines are
392 ;; significant and trigger hard line breaks. As such, `gfm-mode' turns off
393 ;; `auto-fill-mode' and turns on `visual-line-mode' (or `longlines-mode' if
394 ;; `visual-line-mode' is not available). Wiki links in this mode will be
395 ;; treated as on GitHub, with hyphens replacing spaces in filenames and
396 ;; where the first letter of the filename capitalized. For example,
397 ;; `[[wiki link]]' will map to a file named `Wiki-link` with the same
398 ;; extension as the current file.
400 ;;; Acknowledgments:
402 ;; markdown-mode has benefited greatly from the efforts of the
403 ;; following people:
405 ;; * Cyril Brulebois <cyril.brulebois@enst-bretagne.fr> for Debian packaging.
406 ;; * Conal Elliott <conal@conal.net> for a font-lock regexp patch.
407 ;; * Edward O'Connor <hober0@gmail.com> for a font-lock regexp fix and
408 ;; GitHub Flavored Markdown mode (`gfm-mode').
409 ;; * Greg Bognar <greg_bognar@hms.harvard.edu> for menus and running
410 ;; `markdown' with an active region.
411 ;; * Daniel Burrows <dburrows@debian.org> for filing Debian bug #456592.
412 ;; * Peter S. Galbraith <psg@debian.org> for maintaining emacs-goodies-el.
413 ;; * Dmitry Dzhus <mail@sphinx.net.ru> for reference checking functions.
414 ;; * Bryan Kyle <bryan.kyle@gmail.com> for indentation code.
415 ;; * Ben Voui <intrigeri@boum.org> for font-lock face customizations.
416 ;; * Ankit Solanki <ankit.solanki@gmail.com> for longlines.el
417 ;; compatibility and custom CSS.
418 ;; * Hilko Bengen <bengen@debian.org> for proper XHTML output.
419 ;; * Jose A. Ortega Ruiz <jao@gnu.org> for Emacs 23 fixes.
420 ;; * Alec Resnick <alec@sproutward.org> for bug reports.
421 ;; * Joost Kremers <joostkremers@fastmail.fm> for footnote-handling
422 ;; functions and bug reports regarding indentation.
423 ;; * Peter Williams <pezra@barelyenough.org> for fill-paragraph
424 ;; enhancements.
425 ;; * George Ogata <george.ogata@gmail.com> for fixing several
426 ;; byte-compilation warnings.
427 ;; * Eric Merritt <ericbmerritt@gmail.com> for wiki link features.
428 ;; * Philippe Ivaldi <pivaldi@sfr.fr> for XHTML preview
429 ;; customizations and XHTML export.
430 ;; * Jeremiah Dodds <jeremiah.dodds@gmail.com> for supporting
431 ;; Markdown processors which do not accept input from stdin.
432 ;; * Werner Dittmann <werner.dittmann@t-online.de> for bug reports
433 ;; regarding the cl dependency and auto-fill-mode and indentation.
434 ;; * Scott Pfister <scott.pfister@gmail.com> for generalizing the space
435 ;; substitution character for mapping wiki links to filenames.
436 ;; * Marcin Kasperski <marcin.kasperski@mekk.waw.pl> for a patch to
437 ;; escape shell commands.
438 ;; * Christopher J. Madsen <cjm@cjmweb.net> for patches to fix a match
439 ;; data bug and to prefer `visual-line-mode' in `gfm-mode'.
440 ;; * Shigeru Fukaya <shigeru.fukaya@gmail.com> for better adherence to
441 ;; Emacs Lisp coding conventions.
442 ;; * Donald Ephraim Curtis <dcurtis@milkbox.net> for fixing the `paragraph-fill'
443 ;; regexp, refactoring the compilation and preview functions,
444 ;; heading font-lock generalizations, list renumbering,
445 ;; and kill ring save.
446 ;; * Kevin Porter <kportertx@gmail.com> for wiki link handling in `gfm-mode'.
447 ;; * Max Penet <max.penet@gmail.com> and Peter Eisentraut <peter_e@gmx.net>
448 ;; for an autoload token for `gfm-mode'.
449 ;; * Ian Yang <me@iany.me> for improving the reference definition regex.
450 ;; * Akinori Musha <knu@idaemons.org> for an imenu index function.
451 ;; * Michael Sperber <sperber@deinprogramm.de> for XEmacs fixes.
452 ;; * Francois Gannaz <francois.gannaz@free.fr> for suggesting charset
453 ;; declaration in XHTML output.
454 ;; * Zhenlei Jia <zhenlei.jia@gmail.com> for smart (dedention)
455 ;; un-indentation function.
456 ;; * Matus Goljer <dota.keys@gmail.com> for improved wiki link following.
457 ;; * Peter Jones <pjones@pmade.com> for link following functions.
458 ;; * Bryan Fink <bryan.fink@gmail.com> for a bug report regarding
459 ;; externally modified files.
460 ;; * Vegard Vesterheim <vegard.vesterheim@uninett.no> and Carsten Dominik
461 ;; for a bug fix related to orgtbl-mode.
463 ;;; Bugs:
465 ;; Although markdown-mode is developed and tested primarily using
466 ;; GNU Emacs 24, compatibility with earlier Emacsen is also a
467 ;; priority.
469 ;; If you find any bugs in markdown-mode, please construct a test case
470 ;; or a patch and email me at <jrblevin@sdf.org>.
472 ;;; History:
474 ;; markdown-mode was written and is maintained by Jason Blevins. The
475 ;; first version was released on May 24, 2007.
477 ;; * 2007-05-24: Version 1.1
478 ;; * 2007-05-25: Version 1.2
479 ;; * 2007-06-05: [Version 1.3][]
480 ;; * 2007-06-29: Version 1.4
481 ;; * 2008-05-24: [Version 1.5][]
482 ;; * 2008-06-04: [Version 1.6][]
483 ;; * 2009-10-01: [Version 1.7][]
484 ;; * 2011-08-12: [Version 1.8][]
485 ;; * 2011-08-15: [Version 1.8.1][]
486 ;; * 2013-01-25: [Version 1.9][]
488 ;; [Version 1.3]: http://jblevins.org/projects/markdown-mode/rev-1-3
489 ;; [Version 1.5]: http://jblevins.org/projects/markdown-mode/rev-1-5
490 ;; [Version 1.6]: http://jblevins.org/projects/markdown-mode/rev-1-6
491 ;; [Version 1.7]: http://jblevins.org/projects/markdown-mode/rev-1-7
492 ;; [Version 1.8]: http://jblevins.org/projects/markdown-mode/rev-1-8
493 ;; [Version 1.8.1]: http://jblevins.org/projects/markdown-mode/rev-1-8-1
494 ;; [Version 1.9]: http://jblevins.org/projects/markdown-mode/rev-1-9
497 ;;; Code:
499 (require 'easymenu)
500 (require 'outline)
501 (eval-when-compile (require 'cl))
503 ;;; Constants =================================================================
505 (defconst markdown-mode-version "1.9"
506 "Markdown mode version number.")
508 (defconst markdown-output-buffer-name "*markdown-output*"
509 "Name of temporary buffer for markdown command output.")
511 ;;; Customizable variables ====================================================
513 (defvar markdown-mode-hook nil
514 "Hook run when entering Markdown mode.")
516 (defgroup markdown nil
517 "Major mode for editing text files in Markdown format."
518 :prefix "markdown-"
519 :group 'wp
520 :link '(url-link "http://jblevins.org/projects/markdown-mode/"))
522 (defcustom markdown-command "markdown"
523 "Command to run markdown."
524 :group 'markdown
525 :type 'string)
527 (defcustom markdown-command-needs-filename nil
528 "Set to non-nil if `markdown-command' does not accept input from stdin.
529 Instead, it will be passed a filename as the final command-line
530 option. As a result, you will only be able to run Markdown from
531 buffers which are visiting a file."
532 :group 'markdown
533 :type 'boolean)
535 (defcustom markdown-open-command nil
536 "Command used for opening Markdown files directly.
537 For example, a standalone Markdown previewer. This command will
538 be called with a single argument: the filename of the current
539 buffer."
540 :group 'markdown
541 :type 'string)
543 (defcustom markdown-hr-string "* * * * *"
544 "String to use for horizonal rules."
545 :group 'markdown
546 :type 'string)
548 (defcustom markdown-bold-underscore nil
549 "Use two underscores for bold instead of two asterisks."
550 :group 'markdown
551 :type 'boolean)
553 (defcustom markdown-italic-underscore nil
554 "Use underscores for italic instead of asterisks."
555 :group 'markdown
556 :type 'boolean)
558 (defcustom markdown-indent-function 'markdown-indent-line
559 "Function to use to indent."
560 :group 'markdown
561 :type 'function)
563 (defcustom markdown-indent-on-enter t
564 "Automatically indent new lines when enter key is pressed."
565 :group 'markdown
566 :type 'boolean)
568 (defcustom markdown-follow-wiki-link-on-enter t
569 "Follow wiki link at point (if any) when the enter key is pressed."
570 :group 'markdown
571 :type 'boolean)
573 (defcustom markdown-wiki-link-alias-first t
574 "When non-nil, treat aliased wiki links like [[alias text|PageName]].
575 Otherwise, they will be treated as [[PageName|alias text]]."
576 :group 'markdown
577 :type 'boolean)
579 (defcustom markdown-uri-types
580 '("acap" "cid" "data" "dav" "fax" "file" "ftp" "gopher" "http" "https"
581 "imap" "ldap" "mailto" "mid" "modem" "news" "nfs" "nntp" "pop" "prospero"
582 "rtsp" "service" "sip" "tel" "telnet" "tip" "urn" "vemmi" "wais")
583 "Link types for syntax highlighting of URIs."
584 :group 'markdown
585 :type 'list)
587 (defcustom markdown-enable-math nil
588 "Syntax highlighting for inline LaTeX expressions.
589 This will not take effect until Emacs is restarted."
590 :group 'markdown
591 :type 'boolean)
593 (defcustom markdown-css-path ""
594 "URL of CSS file to link to in the output XHTML."
595 :group 'markdown
596 :type 'string)
598 (defcustom markdown-content-type ""
599 "Content type string for the http-equiv header in XHTML output.
600 When set to a non-empty string, insert the http-equiv attribute.
601 Otherwise, this attribute is omitted."
602 :group 'markdown
603 :type 'string)
605 (defcustom markdown-coding-system nil
606 "Character set string for the http-equiv header in XHTML output.
607 Defaults to `buffer-file-coding-system' (and falling back to
608 `iso-8859-1' when not available). Common settings are `utf-8'
609 and `iso-latin-1'. Use `list-coding-systems' for more choices."
610 :group 'markdown
611 :type 'coding-system)
613 (defcustom markdown-xhtml-header-content ""
614 "Additional content to include in the XHTML <head> block."
615 :group 'markdown
616 :type 'string)
618 (defcustom markdown-xhtml-standalone-regexp
619 "^\\(\<\?xml\\|\<!DOCTYPE\\|\<html\\)"
620 "Regexp indicating whether `markdown-command' output is standalone XHTML."
621 :group 'markdown
622 :type 'regexp)
624 (defcustom markdown-link-space-sub-char
626 "Character to use instead of spaces when mapping wiki links to filenames."
627 :group 'markdown
628 :type 'string)
630 (defcustom markdown-footnote-location 'end
631 "Position where new footnotes are inserted in the document."
632 :group 'markdown
633 :type '(choice (const :tag "At the end of the document" end)
634 (const :tag "Immediately after the paragraph" immediately)
635 (const :tag "Before next header" header)))
637 ;;; Font lock =================================================================
639 (require 'font-lock)
641 (defvar markdown-italic-face 'markdown-italic-face
642 "Face name to use for italic text.")
644 (defvar markdown-bold-face 'markdown-bold-face
645 "Face name to use for bold text.")
647 (defvar markdown-header-delimiter-face 'markdown-header-delimiter-face
648 "Face name to use as a base for header delimiters.")
650 (defvar markdown-header-rule-face 'markdown-header-rule-face
651 "Face name to use as a base for header rules.")
653 (defvar markdown-header-face 'markdown-header-face
654 "Face name to use as a base for headers.")
656 (defvar markdown-header-face-1 'markdown-header-face-1
657 "Face name to use for level-1 headers.")
659 (defvar markdown-header-face-2 'markdown-header-face-2
660 "Face name to use for level-2 headers.")
662 (defvar markdown-header-face-3 'markdown-header-face-3
663 "Face name to use for level-3 headers.")
665 (defvar markdown-header-face-4 'markdown-header-face-4
666 "Face name to use for level-4 headers.")
668 (defvar markdown-header-face-5 'markdown-header-face-5
669 "Face name to use for level-5 headers.")
671 (defvar markdown-header-face-6 'markdown-header-face-6
672 "Face name to use for level-6 headers.")
674 (defvar markdown-inline-code-face 'markdown-inline-code-face
675 "Face name to use for inline code.")
677 (defvar markdown-list-face 'markdown-list-face
678 "Face name to use for list markers.")
680 (defvar markdown-blockquote-face 'markdown-blockquote-face
681 "Face name to use for blockquote.")
683 (defvar markdown-pre-face 'markdown-pre-face
684 "Face name to use for preformatted text.")
686 (defvar markdown-link-face 'markdown-link-face
687 "Face name to use for links.")
689 (defvar markdown-missing-link-face 'markdown-missing-link-face
690 "Face name to use for links where the linked file does not exist.")
692 (defvar markdown-reference-face 'markdown-reference-face
693 "Face name to use for reference.")
695 (defvar markdown-footnote-face 'markdown-footnote-face
696 "Face name to use for footnote identifiers.")
698 (defvar markdown-url-face 'markdown-url-face
699 "Face name to use for URLs.")
701 (defvar markdown-link-title-face 'markdown-link-title-face
702 "Face name to use for reference link titles.")
704 (defvar markdown-comment-face 'markdown-comment-face
705 "Face name to use for HTML comments.")
707 (defvar markdown-math-face 'markdown-math-face
708 "Face name to use for LaTeX expressions.")
710 (defgroup markdown-faces nil
711 "Faces used in Markdown Mode"
712 :group 'markdown
713 :group 'faces)
715 (defface markdown-italic-face
716 '((t (:inherit font-lock-variable-name-face :slant italic)))
717 "Face for italic text."
718 :group 'markdown-faces)
720 (defface markdown-bold-face
721 '((t (:inherit font-lock-variable-name-face :weight bold)))
722 "Face for bold text."
723 :group 'markdown-faces)
725 (defface markdown-header-rule-face
726 '((t (:inherit font-lock-function-name-face :weight bold)))
727 "Base face for headers rules."
728 :group 'markdown-faces)
730 (defface markdown-header-delimiter-face
731 '((t (:inherit font-lock-function-name-face :weight bold)))
732 "Base face for headers hash delimiter."
733 :group 'markdown-faces)
735 (defface markdown-header-face
736 '((t (:inherit font-lock-function-name-face :weight bold)))
737 "Base face for headers."
738 :group 'markdown-faces)
740 (defface markdown-header-face-1
741 '((t (:inherit markdown-header-face)))
742 "Face for level-1 headers."
743 :group 'markdown-faces)
745 (defface markdown-header-face-2
746 '((t (:inherit markdown-header-face)))
747 "Face for level-2 headers."
748 :group 'markdown-faces)
750 (defface markdown-header-face-3
751 '((t (:inherit markdown-header-face)))
752 "Face for level-3 headers."
753 :group 'markdown-faces)
755 (defface markdown-header-face-4
756 '((t (:inherit markdown-header-face)))
757 "Face for level-4 headers."
758 :group 'markdown-faces)
760 (defface markdown-header-face-5
761 '((t (:inherit markdown-header-face)))
762 "Face for level-5 headers."
763 :group 'markdown-faces)
765 (defface markdown-header-face-6
766 '((t (:inherit markdown-header-face)))
767 "Face for level-6 headers."
768 :group 'markdown-faces)
770 (defface markdown-inline-code-face
771 '((t (:inherit font-lock-constant-face)))
772 "Face for inline code."
773 :group 'markdown-faces)
775 (defface markdown-list-face
776 '((t (:inherit font-lock-builtin-face)))
777 "Face for list item markers."
778 :group 'markdown-faces)
780 (defface markdown-blockquote-face
781 '((t (:inherit font-lock-doc-face)))
782 "Face for blockquote sections."
783 :group 'markdown-faces)
785 (defface markdown-pre-face
786 '((t (:inherit font-lock-constant-face)))
787 "Face for preformatted text."
788 :group 'markdown-faces)
790 (defface markdown-link-face
791 '((t (:inherit font-lock-keyword-face)))
792 "Face for links."
793 :group 'markdown-faces)
795 (defface markdown-missing-link-face
796 '((t (:inherit font-lock-warning-face)))
797 "Face for missing links."
798 :group 'markdown-faces)
800 (defface markdown-reference-face
801 '((t (:inherit font-lock-type-face)))
802 "Face for link references."
803 :group 'markdown-faces)
805 (defface markdown-footnote-face
806 '((t (:inherit font-lock-keyword-face)))
807 "Face for footnote markers."
808 :group 'markdown-faces)
810 (defface markdown-url-face
811 '((t (:inherit font-lock-string-face)))
812 "Face for URLs."
813 :group 'markdown-faces)
815 (defface markdown-link-title-face
816 '((t (:inherit font-lock-comment-face)))
817 "Face for reference link titles."
818 :group 'markdown-faces)
820 (defface markdown-comment-face
821 '((t (:inherit font-lock-comment-face)))
822 "Face for HTML comments."
823 :group 'markdown-faces)
825 (defface markdown-math-face
826 '((t (:inherit font-lock-string-face)))
827 "Face for LaTeX expressions."
828 :group 'markdown-faces)
830 (defconst markdown-regex-link-inline
831 "\\(!?\\[[^]]*?\\]\\)\\(([^\\)]*)\\)"
832 "Regular expression for a [text](file) or an image link ![text](file).")
834 (defconst markdown-regex-link-reference
835 "\\(!?\\[[^]]+?\\]\\)[ ]?\\(\\[[^]]*?\\]\\)"
836 "Regular expression for a reference link [text][id].")
838 (defconst markdown-regex-reference-definition
839 "^ \\{0,3\\}\\(\\[[^^\n]+?\\]\\):\\s *\\(.*?\\)\\s *\\( \"[^\"]*\"$\\|$\\)"
840 "Regular expression for a link definition [id]: ...")
842 (defconst markdown-regex-footnote
843 "\\(\\[\\^.+?\\]\\)"
844 "Regular expression for a footnote marker [^fn].")
846 (defconst markdown-regex-header
847 "^\\(?:\\(.+\\)\n\\(===+\\)\\|\\(.+\\)\n\\(---+\\)\\|\\(#+\\)\\s-*\\(.*?\\)\\s-*?\\(#*\\)\\)$"
848 "Regexp identifying Markdown headers.")
850 (defconst markdown-regex-header-1-atx
851 "^\\(# \\)\\(.*?\\)\\($\\| #+$\\)"
852 "Regular expression for level 1 atx-style (hash mark) headers.")
854 (defconst markdown-regex-header-2-atx
855 "^\\(## \\)\\(.*?\\)\\($\\| #+$\\)"
856 "Regular expression for level 2 atx-style (hash mark) headers.")
858 (defconst markdown-regex-header-3-atx
859 "^\\(### \\)\\(.*?\\)\\($\\| #+$\\)"
860 "Regular expression for level 3 atx-style (hash mark) headers.")
862 (defconst markdown-regex-header-4-atx
863 "^\\(#### \\)\\(.*?\\)\\($\\| #+$\\)"
864 "Regular expression for level 4 atx-style (hash mark) headers.")
866 (defconst markdown-regex-header-5-atx
867 "^\\(##### \\)\\(.*?\\)\\($\\| #+$\\)"
868 "Regular expression for level 5 atx-style (hash mark) headers.")
870 (defconst markdown-regex-header-6-atx
871 "^\\(###### \\)\\(.*?\\)\\($\\| #+$\\)"
872 "Regular expression for level 6 atx-style (hash mark) headers.")
874 (defconst markdown-regex-header-1-setext
875 "^\\(.*\\)\n\\(===+\\)$"
876 "Regular expression for level 1 setext-style (underline) headers.")
878 (defconst markdown-regex-header-2-setext
879 "^\\(.*\\)\n\\(---+\\)$"
880 "Regular expression for level 2 setext-style (underline) headers.")
882 (defconst markdown-regex-hr
883 "^\\(\\*[ ]?\\*[ ]?\\*[ ]?[\\* ]*\\|-[ ]?-[ ]?-[--- ]*\\)$"
884 "Regular expression for matching Markdown horizontal rules.")
886 (defconst markdown-regex-code
887 "\\(^\\|[^\\]\\)\\(\\(`\\{1,2\\}\\)\\([^ \\]\\|[^ ]\\(.\\|\n[^\n]\\)*?[^ \\]\\)\\3\\)"
888 "Regular expression for matching inline code fragments.")
890 (defconst markdown-regex-pre
891 "^\\( \\|\t\\).*$"
892 "Regular expression for matching preformatted text sections.")
894 (defconst markdown-regex-list
895 "^[ \t]*\\([0-9]+\\.\\|[\\*\\+-]\\) "
896 "Regular expression for matching list markers.")
898 (defconst markdown-regex-bold
899 "\\(^\\|[^\\]\\)\\(\\([*_]\\{2\\}\\)\\(.\\|\n[^\n]\\)*?[^\\ ]\\3\\)"
900 "Regular expression for matching bold text.")
902 (defconst markdown-regex-italic
903 "\\(^\\|[^\\]\\)\\(\\([*_]\\)\\([^ \\]\\3\\|[^ ]\\(.\\|\n[^\n]\\)*?[^\\ ]\\3\\)\\)"
904 "Regular expression for matching italic text.")
906 (defconst markdown-regex-blockquote
907 "^>.*$"
908 "Regular expression for matching blockquote lines.")
910 (defconst markdown-regex-line-break
911 " $"
912 "Regular expression for matching line breaks.")
914 (defconst markdown-regex-wiki-link
915 "\\[\\[\\([^]|]+\\)\\(|\\([^]]+\\)\\)?\\]\\]"
916 "Regular expression for matching wiki links.
917 This matches typical bracketed [[WikiLinks]] as well as 'aliased'
918 wiki links of the form [[PageName|link text]]. In this regular
919 expression, #1 matches the page name and #3 matches the link
920 text.")
922 (defconst markdown-regex-uri
923 (concat
924 "\\(" (mapconcat 'identity markdown-uri-types "\\|")
925 "\\):[^]\t\n\r<>,;() ]+")
926 "Regular expression for matching inline URIs.")
928 (defconst markdown-regex-angle-uri
929 (concat
930 "\\(<\\)\\(\\(?:"
931 (mapconcat 'identity markdown-uri-types "\\|")
932 "\\):[^]\t\n\r<>,;()]+\\)\\(>\\)")
933 "Regular expression for matching inline URIs in angle brackets.")
935 (defconst markdown-regex-email
936 "<\\(\\sw\\|\\s_\\|\\s.\\)+@\\(\\sw\\|\\s_\\|\\s.\\)+>"
937 "Regular expression for matching inline email addresses.")
939 (defconst markdown-regex-latex-expression
940 "\\(^\\|[^\\]\\)\\(\\$\\($\\([^\\$]\\|\\\\.\\)*\\$\\|\\([^\\$]\\|\\\\.\\)*\\)\\$\\)"
941 "Regular expression for itex $..$ or $$..$$ math mode expressions.")
943 (defconst markdown-regex-latex-display
944 "^\\\\\\[\\(.\\|\n\\)*?\\\\\\]$"
945 "Regular expression for itex \[..\] display mode expressions.")
947 (defconst markdown-regex-list-indent
948 "^\\(\\s *\\)\\([0-9]+\\.\\|[\\*\\+-]\\)\\(\\s +\\)"
949 "Regular expression for matching indentation of list items.")
951 (defvar markdown-mode-font-lock-keywords-basic
952 (list
953 '(markdown-match-pre-blocks 0 markdown-pre-face t t)
954 '(markdown-match-fenced-code-blocks 0 markdown-pre-face t t)
955 (cons markdown-regex-blockquote 'markdown-blockquote-face)
956 (cons markdown-regex-header-1-setext '((1 markdown-header-face-1)
957 (2 markdown-header-rule-face)))
958 (cons markdown-regex-header-2-setext '((1 markdown-header-face-2)
959 (2 markdown-header-rule-face)))
960 (cons markdown-regex-header-1-atx '((1 markdown-header-delimiter-face)
961 (2 markdown-header-face-1)
962 (3 markdown-header-delimiter-face)))
963 (cons markdown-regex-header-2-atx '((1 markdown-header-delimiter-face)
964 (2 markdown-header-face-2)
965 (3 markdown-header-delimiter-face)))
966 (cons markdown-regex-header-3-atx '((1 markdown-header-delimiter-face)
967 (2 markdown-header-face-3)
968 (3 markdown-header-delimiter-face)))
969 (cons markdown-regex-header-4-atx '((1 markdown-header-delimiter-face)
970 (2 markdown-header-face-4)
971 (3 markdown-header-delimiter-face)))
972 (cons markdown-regex-header-5-atx '((1 markdown-header-delimiter-face)
973 (2 markdown-header-face-5)
974 (3 markdown-header-delimiter-face)))
975 (cons markdown-regex-header-6-atx '((1 markdown-header-delimiter-face)
976 (2 markdown-header-face-6)
977 (3 markdown-header-delimiter-face)))
978 (cons markdown-regex-hr 'markdown-header-face)
979 '(markdown-match-comments 0 markdown-comment-face t t)
980 (cons markdown-regex-code '(2 markdown-inline-code-face))
981 (cons markdown-regex-angle-uri 'markdown-link-face)
982 (cons markdown-regex-uri 'markdown-link-face)
983 (cons markdown-regex-email 'markdown-link-face)
984 (cons markdown-regex-list 'markdown-list-face)
985 (cons markdown-regex-link-inline
986 '((1 markdown-link-face t)
987 (2 markdown-url-face t)))
988 (cons markdown-regex-link-reference
989 '((1 markdown-link-face t)
990 (2 markdown-reference-face t)))
991 (cons markdown-regex-reference-definition
992 '((1 markdown-reference-face t)
993 (2 markdown-url-face t)
994 (3 markdown-link-title-face t)))
995 (cons markdown-regex-footnote 'markdown-footnote-face)
996 (cons markdown-regex-bold '(2 markdown-bold-face))
997 (cons markdown-regex-italic '(2 markdown-italic-face))
999 "Syntax highlighting for Markdown files.")
1001 (defconst markdown-mode-font-lock-keywords-latex
1002 (list
1003 ;; Math mode $..$ or $$..$$
1004 (cons markdown-regex-latex-expression '(2 markdown-math-face))
1005 ;; Display mode equations with brackets: \[ \]
1006 (cons markdown-regex-latex-display 'markdown-math-face)
1007 ;; Equation reference (eq:foo)
1008 (cons "(eq:\\w+)" 'markdown-reference-face)
1009 ;; Equation reference \eqref{foo}
1010 (cons "\\\\eqref{\\w+}" 'markdown-reference-face))
1011 "Syntax highlighting for LaTeX fragments.")
1013 (defvar markdown-mode-font-lock-keywords
1014 (append
1015 (if markdown-enable-math
1016 markdown-mode-font-lock-keywords-latex)
1017 markdown-mode-font-lock-keywords-basic)
1018 "Default highlighting expressions for Markdown mode.")
1020 ;; Footnotes
1021 (defvar markdown-footnote-counter 0
1022 "Counter for footnote numbers.")
1023 (make-variable-buffer-local 'markdown-footnote-counter)
1025 (defconst markdown-footnote-chars
1026 "[[:alnum:]-]"
1027 "Regular expression maching any character that is allowed in a footnote identifier.")
1031 ;;; Compatibility =============================================================
1033 ;; Handle replace-regexp-in-string in XEmacs 21
1034 (defun markdown-replace-regexp-in-string (regexp rep string)
1035 "Compatibility wrapper to provide `replace-regexp-in-string'."
1036 (if (featurep 'xemacs)
1037 (replace-in-string string regexp rep)
1038 (replace-regexp-in-string regexp rep string)))
1040 (eval-and-compile
1041 (if (boundp 'mark-active)
1042 (defun markdown-mark-active () ; Emacs
1043 mark-active)
1044 (defalias 'markdown-mark-active 'region-exists-p))) ; XEmacs
1046 (defun markdown-transient-mark-mode-active ()
1047 (cond
1048 ((boundp 'transient-mark-mode)
1049 (and transient-mark-mode (markdown-mark-active)))
1050 ((boundp 'zmacs-regions)
1051 (and zmacs-regions (markdown-mark-active)))))
1055 ;;; Markdown parsing functions ================================================
1057 (defun markdown-cur-line-blank-p ()
1058 "Return t if the current line is blank and nil otherwise."
1059 (save-excursion
1060 (beginning-of-line)
1061 (re-search-forward "^\\s *$" (point-at-eol) t)))
1063 (defun markdown-prev-line-blank-p ()
1064 "Return t if the previous line is blank and nil otherwise.
1065 If we are at the first line, then consider the previous line to be blank."
1066 (save-excursion
1067 (if (= (point-at-bol) (point-min))
1069 (forward-line -1)
1070 (markdown-cur-line-blank-p))))
1072 (defun markdown-next-line-blank-p ()
1073 "Return t if the next line is blank and nil otherwise.
1074 If we are at the last line, then consider the next line to be blank."
1075 (save-excursion
1076 (if (= (point-at-bol) (point-max))
1078 (forward-line 1)
1079 (markdown-cur-line-blank-p))))
1081 (defun markdown-prev-line-indent-p ()
1082 "Return t if the previous line is indented and nil otherwise."
1083 (save-excursion
1084 (forward-line -1)
1085 (goto-char (point-at-bol))
1086 (if (re-search-forward "^\\s " (point-at-eol) t) t)))
1088 (defun markdown-cur-line-indent ()
1089 "Return the number of leading whitespace characters in the current line."
1090 (save-excursion
1091 (goto-char (point-at-bol))
1092 (re-search-forward "^\\s +" (point-at-eol) t)
1093 (current-column)))
1095 (defun markdown-prev-line-indent ()
1096 "Return the number of leading whitespace characters in the previous line."
1097 (save-excursion
1098 (forward-line -1)
1099 (markdown-cur-line-indent)))
1101 (defun markdown-next-line-indent ()
1102 "Return the number of leading whitespace characters in the next line."
1103 (save-excursion
1104 (forward-line 1)
1105 (markdown-cur-line-indent)))
1107 (defun markdown-cur-non-list-indent ()
1108 "Return the number of leading whitespace characters in the current line."
1109 (save-excursion
1110 (beginning-of-line)
1111 (when (re-search-forward markdown-regex-list-indent (point-at-eol) t)
1112 (current-column))))
1114 (defun markdown-prev-non-list-indent ()
1115 "Return position of the first non-list-marker on the previous line."
1116 (save-excursion
1117 (forward-line -1)
1118 (markdown-cur-non-list-indent)))
1120 (defun markdown--next-block ()
1121 "Move the point to the start of the next text block."
1122 (forward-line)
1123 (while (and (or (not (markdown-prev-line-blank-p))
1124 (markdown-cur-line-blank-p))
1125 (not (eobp)))
1126 (forward-line)))
1128 (defun markdown--end-of-level (level)
1129 "Move the point to the end of region with indentation at least LEVEL."
1130 (let (indent)
1131 (while (and (not (< (setq indent (markdown-cur-line-indent)) level))
1132 (not (>= indent (+ level 4)))
1133 (not (eobp)))
1134 (markdown--next-block))
1135 (unless (eobp)
1136 ;; Move back before any trailing blank lines
1137 (while (and (markdown-prev-line-blank-p)
1138 (not (bobp)))
1139 (forward-line -1))
1140 (forward-line -1)
1141 (end-of-line))))
1143 ;; From html-helper-mode
1144 (defun markdown-match-comments (last)
1145 "Match HTML comments from the point to LAST."
1146 (cond ((search-forward "<!--" last t)
1147 (backward-char 4)
1148 (let ((beg (point)))
1149 (cond ((search-forward-regexp "--[ \t]*>" last t)
1150 (set-match-data (list beg (point)))
1152 (t nil))))
1153 (t nil)))
1155 (defun markdown-match-pre-blocks (last)
1156 "Match Markdown pre blocks from point to LAST.
1157 A region matches as if it is indented at least four spaces
1158 relative to the nearest previous block of lesser non-list-marker
1159 indentation."
1161 (let (cur-begin cur-end cur-indent prev-indent prev-list stop match found)
1162 ;; Don't start in the middle of a block
1163 (unless (and (bolp)
1164 (markdown-prev-line-blank-p)
1165 (not (markdown-cur-line-blank-p)))
1166 (markdown--next-block))
1168 ;; Move to the first full block in the region with indent 4 or more
1169 (while (and (not (>= (setq cur-indent (markdown-cur-line-indent)) 4))
1170 (not (>= (point) last)))
1171 (markdown--next-block))
1172 (setq cur-begin (point))
1173 (markdown--end-of-level cur-indent)
1174 (setq cur-end (point))
1175 (setq match nil)
1176 (setq stop (> cur-begin cur-end))
1178 (while (and (<= cur-end last) (not stop) (not match))
1179 ;; Move to the nearest preceding block of lesser (non-marker) indentation
1180 (setq prev-indent (+ cur-indent 1))
1181 (goto-char cur-begin)
1182 (setq found nil)
1183 (while (and (>= prev-indent cur-indent)
1184 (not (and prev-list
1185 (eq prev-indent cur-indent)))
1186 (not (bobp)))
1188 ;; Move point to the last line of the previous block.
1189 (forward-line -1)
1190 (while (and (markdown-cur-line-blank-p)
1191 (not (bobp)))
1192 (forward-line -1))
1194 ;; Update the indentation level using either the
1195 ;; non-list-marker indentation, if the previous line is the
1196 ;; start of a list, or the actual indentation.
1197 (setq prev-list (markdown-cur-non-list-indent))
1198 (setq prev-indent (or prev-list
1199 (markdown-cur-line-indent)))
1200 (setq found t))
1202 ;; If the loop didn't execute
1203 (unless found
1204 (setq prev-indent 0))
1206 ;; Compare with prev-indent minus its remainder mod 4
1207 (setq prev-indent (- prev-indent (mod prev-indent 4)))
1209 ;; Set match data and return t if we have a match
1210 (if (>= cur-indent (+ prev-indent 4))
1211 ;; Match
1212 (progn
1213 (setq match t)
1214 (set-match-data (list cur-begin cur-end))
1215 ;; Leave point at end of block
1216 (goto-char cur-end)
1217 (forward-line))
1219 ;; Move to the next block (if possible)
1220 (goto-char cur-end)
1221 (markdown--next-block)
1222 (setq cur-begin (point))
1223 (setq cur-indent (markdown-cur-line-indent))
1224 (markdown--end-of-level cur-indent)
1225 (setq cur-end (point))
1226 (setq stop (equal cur-begin cur-end))))
1227 match))
1229 (defun markdown-match-fenced-code-blocks (last)
1230 "Match fenced code blocks from the point to LAST."
1231 (cond ((search-forward-regexp "^\\([~]\\{3,\\}\\)" last t)
1232 (beginning-of-line)
1233 (let ((beg (point)))
1234 (forward-line)
1235 (cond ((search-forward-regexp
1236 (concat "^" (match-string 1) "~*") last t)
1237 (set-match-data (list beg (point)))
1239 (t nil))))
1240 (t nil)))
1242 (defun markdown-font-lock-extend-region ()
1243 "Extend the search region to include an entire block of text.
1244 This helps improve font locking for block constructs such as pre blocks."
1245 ;; Avoid compiler warnings about these global variables from font-lock.el.
1246 ;; See the documentation for variable `font-lock-extend-region-functions'.
1247 (eval-when-compile (defvar font-lock-beg) (defvar font-lock-end))
1248 (save-excursion
1249 (goto-char font-lock-beg)
1250 (let ((found (re-search-backward "\n\n" nil t)))
1251 (when found
1252 (goto-char font-lock-end)
1253 (when (re-search-forward "\n\n" nil t)
1254 (beginning-of-line)
1255 (setq font-lock-end (point)))
1256 (setq font-lock-beg found)))))
1260 ;;; Syntax Table ==============================================================
1262 (defvar markdown-mode-syntax-table
1263 (let ((markdown-mode-syntax-table (make-syntax-table)))
1264 (modify-syntax-entry ?\" "w" markdown-mode-syntax-table)
1265 markdown-mode-syntax-table)
1266 "Syntax table for `markdown-mode'.")
1270 ;;; Element Insertion =========================================================
1272 (defun markdown-wrap-or-insert (s1 s2)
1273 "Insert the strings S1 and S2.
1274 If Transient Mark mode is on and a region is active, wrap the strings S1
1275 and S2 around the region."
1276 (if (markdown-transient-mark-mode-active)
1277 (let ((a (region-beginning)) (b (region-end)))
1278 (goto-char a)
1279 (insert s1)
1280 (goto-char (+ b (length s1)))
1281 (insert s2))
1282 (insert s1 s2)))
1284 (defun markdown-insert-hr ()
1285 "Insert a horizonal rule using `markdown-hr-string'."
1286 (interactive)
1287 ;; Leading blank line
1288 (when (and (>= (point) (+ (point-min) 2))
1289 (not (looking-back "\n\n" 2)))
1290 (insert "\n"))
1291 ;; Insert custom HR string
1292 (insert (concat markdown-hr-string "\n"))
1293 ;; Following blank line
1294 (backward-char)
1295 (unless (looking-at "\n\n")
1296 (insert "\n")))
1298 (defun markdown-insert-bold ()
1299 "Insert markup for a bold word or phrase.
1300 If Transient Mark mode is on and a region is active, it is made bold."
1301 (interactive)
1302 (if markdown-bold-underscore
1303 (markdown-wrap-or-insert "__" "__")
1304 (markdown-wrap-or-insert "**" "**"))
1305 (backward-char 2))
1307 (defun markdown-insert-italic ()
1308 "Insert markup for an italic word or phrase.
1309 If Transient Mark mode is on and a region is active, it is made italic."
1310 (interactive)
1311 (if markdown-italic-underscore
1312 (markdown-wrap-or-insert "_" "_")
1313 (markdown-wrap-or-insert "*" "*"))
1314 (backward-char 1))
1316 (defun markdown-insert-code ()
1317 "Insert markup for an inline code fragment.
1318 If Transient Mark mode is on and a region is active, it is marked
1319 as inline code."
1320 (interactive)
1321 (markdown-wrap-or-insert "`" "`")
1322 (backward-char 1))
1324 (defun markdown-insert-link ()
1325 "Insert an inline link of the form []().
1326 If Transient Mark mode is on and a region is active, it is used
1327 as the link text."
1328 (interactive)
1329 (markdown-wrap-or-insert "[" "]")
1330 (insert "()")
1331 (backward-char 1))
1333 (defun markdown-insert-reference-link-dwim ()
1334 "Insert a reference link of the form [text][label] at point.
1335 If Transient Mark mode is on and a region is active, the region
1336 is used as the link text. Otherwise, the link text will be read
1337 from the minibuffer. The link URL, label, and title will be read
1338 from the minibuffer. The link label definition is placed at the
1339 end of the current paragraph."
1340 (interactive)
1341 (if (markdown-transient-mark-mode-active)
1342 (call-interactively 'markdown-insert-reference-link-region)
1343 (call-interactively 'markdown-insert-reference-link)))
1345 (defun markdown-insert-reference-link-region (url label title)
1346 "Insert a reference link at point using the region as the link text."
1347 (interactive "sLink URL: \nsLink Label (optional): \nsLink Title (optional): ")
1348 (let ((text (buffer-substring (region-beginning) (region-end))))
1349 (delete-region (region-beginning) (region-end))
1350 (markdown-insert-reference-link text url label title)))
1352 (defun markdown-insert-reference-link (text url label title)
1353 "Insert a reference link at point.
1354 The link label definition is placed at the end of the current
1355 paragraph."
1356 (interactive "sLink Text: \nsLink URL: \nsLink Label (optional): \nsLink Title (optional): ")
1357 (let (end)
1358 (insert (concat "[" text "][" label "]"))
1359 (setq end (point))
1360 (forward-paragraph)
1361 (insert "\n[")
1362 (if (> (length label) 0)
1363 (insert label)
1364 (insert text))
1365 (insert (concat "]: " url))
1366 (unless (> (length url) 0)
1367 (setq end (point)))
1368 (when (> (length title) 0)
1369 (insert (concat " \"" title "\"")))
1370 (insert "\n")
1371 (unless (looking-at "\n")
1372 (insert "\n"))
1373 (goto-char end)))
1375 (defun markdown-insert-wiki-link ()
1376 "Insert a wiki link of the form [[WikiLink]].
1377 If Transient Mark mode is on and a region is active, it is used
1378 as the link text."
1379 (interactive)
1380 (markdown-wrap-or-insert "[[" "]]")
1381 (backward-char 2))
1383 (defun markdown-insert-image ()
1384 "Insert an inline image tag of the form ![]().
1385 If Transient Mark mode is on and a region is active, it is used
1386 as the alt text of the image."
1387 (interactive)
1388 (markdown-wrap-or-insert "![" "]")
1389 (insert "()")
1390 (backward-char 1))
1392 (defun markdown-insert-header-1 ()
1393 "Insert a first level atx-style (hash mark) header.
1394 If Transient Mark mode is on and a region is active, it is used
1395 as the header text."
1396 (interactive)
1397 (markdown-insert-header 1))
1399 (defun markdown-insert-header-2 ()
1400 "Insert a second level atx-style (hash mark) header.
1401 If Transient Mark mode is on and a region is active, it is used
1402 as the header text."
1403 (interactive)
1404 (markdown-insert-header 2))
1406 (defun markdown-insert-header-3 ()
1407 "Insert a third level atx-style (hash mark) header.
1408 If Transient Mark mode is on and a region is active, it is used
1409 as the header text."
1410 (interactive)
1411 (markdown-insert-header 3))
1413 (defun markdown-insert-header-4 ()
1414 "Insert a fourth level atx-style (hash mark) header.
1415 If Transient Mark mode is on and a region is active, it is used
1416 as the header text."
1417 (interactive)
1418 (markdown-insert-header 4))
1420 (defun markdown-insert-header-5 ()
1421 "Insert a fifth level atx-style (hash mark) header.
1422 If Transient Mark mode is on and a region is active, it is used
1423 as the header text."
1424 (interactive)
1425 (markdown-insert-header 5))
1427 (defun markdown-insert-header-6 ()
1428 "Insert a sixth level atx-style (hash mark) header.
1429 If Transient Mark mode is on and a region is active, it is used
1430 as the header text."
1431 (interactive)
1432 (markdown-insert-header 6))
1434 (defun markdown-insert-header (n)
1435 "Insert an atx-style (hash mark) header.
1436 With no prefix argument, insert a level-1 header. With prefix N,
1437 insert a level-N header. If Transient Mark mode is on and the
1438 region is active, it is used as the header text."
1439 (interactive "p")
1440 (unless n ; Test to see if n is defined
1441 (setq n 1)) ; Default to level 1 header
1442 (let (hdr hdrl hdrr)
1443 (dotimes (count n hdr)
1444 (setq hdr (concat "#" hdr))) ; Build a hash mark header string
1445 (setq hdrl (concat hdr " "))
1446 (setq hdrr (concat " " hdr))
1447 (markdown-wrap-or-insert hdrl hdrr))
1448 (backward-char (+ 1 n)))
1450 (defun markdown-insert-title ()
1451 "Insert a setext-style (underline) first level header.
1452 If Transient Mark mode is on and a region is active, it is used
1453 as the header text."
1454 (interactive)
1455 (if (markdown-transient-mark-mode-active)
1456 (let ((a (region-beginning))
1457 (b (region-end))
1458 (len 0)
1459 (hdr))
1460 (setq len (- b a))
1461 (dotimes (count len hdr)
1462 (setq hdr (concat "=" hdr))) ; Build a === title underline
1463 (end-of-line)
1464 (insert "\n" hdr "\n"))
1465 (insert "\n==========\n")
1466 (backward-char 12)))
1468 (defun markdown-insert-section ()
1469 "Insert a setext-style (underline) second level header.
1470 If Transient Mark mode is on and a region is active, it is used
1471 as the header text."
1472 (interactive)
1473 (if (markdown-transient-mark-mode-active)
1474 (let ((a (region-beginning))
1475 (b (region-end))
1476 (len 0)
1477 (hdr))
1478 (setq len (- b a))
1479 (dotimes (count len hdr)
1480 (setq hdr (concat "-" hdr))) ; Build a --- section underline
1481 (end-of-line)
1482 (insert "\n" hdr "\n"))
1483 (insert "\n----------\n")
1484 (backward-char 12)))
1486 (defun markdown-insert-blockquote ()
1487 "Start a blockquote section (or blockquote the region).
1488 If Transient Mark mode is on and a region is active, it is used as
1489 the blockquote text."
1490 (interactive)
1491 (if (markdown-transient-mark-mode-active)
1492 (markdown-blockquote-region (region-beginning) (region-end))
1493 (insert "> ")))
1495 (defun markdown-block-region (beg end prefix)
1496 "Format the region using a block prefix.
1497 Arguments BEG and END specify the beginning and end of the
1498 region. The characters PREFIX will appear at the beginning
1499 of each line."
1500 (if mark-active
1501 (save-excursion
1502 ;; Ensure that there is a leading blank line
1503 (goto-char beg)
1504 (when (and (>= (point) (+ (point-min) 2))
1505 (not (looking-back "\n\n" 2)))
1506 (insert "\n")
1507 (setq beg (1+ beg))
1508 (setq end (1+ end)))
1509 ;; Move back before any blank lines at the end
1510 (goto-char end)
1511 (while (and (looking-back "\n" 1)
1512 (not (equal (point) (point-min))))
1513 (backward-char)
1514 (setq end (1- end)))
1515 ;; Ensure that there is a trailing blank line
1516 (goto-char end)
1517 (if (not (or (looking-at "\n\n")
1518 (and (equal (1+ end) (point-max)) (looking-at "\n"))))
1519 (insert "\n"))
1520 ;; Insert PREFIX
1521 (goto-char beg)
1522 (beginning-of-line)
1523 (while (< (point-at-bol) end)
1524 (insert prefix)
1525 (setq end (+ (length prefix) end))
1526 (forward-line)))))
1528 (defun markdown-blockquote-region (beg end)
1529 "Blockquote the region.
1530 Arguments BEG and END specify the beginning and end of the region."
1531 (interactive "*r")
1532 (markdown-block-region beg end "> "))
1534 (defun markdown-insert-pre ()
1535 "Start a preformatted section (or apply to the region).
1536 If Transient Mark mode is on and a region is active, it is marked
1537 as preformatted text."
1538 (interactive)
1539 (if (markdown-transient-mark-mode-active)
1540 (markdown-pre-region (region-beginning) (region-end))
1541 (insert " ")))
1543 (defun markdown-pre-region (beg end)
1544 "Format the region as preformatted text.
1545 Arguments BEG and END specify the beginning and end of the region."
1546 (interactive "*r")
1547 (markdown-block-region beg end " "))
1549 ;;; Footnotes ======================================================================
1551 (defun markdown-footnote-counter-inc ()
1552 "Increment markdown-footnote-counter and return the new value."
1553 (when (= markdown-footnote-counter 0) ; hasn't been updated in this buffer yet.
1554 (save-excursion
1555 (goto-char (point-min))
1556 (while (re-search-forward (concat "^\\[\\^\\(" markdown-footnote-chars "*?\\)\\]:")
1557 (point-max) t)
1558 (let ((fn (string-to-number (match-string 1))))
1559 (when (> fn markdown-footnote-counter)
1560 (setq markdown-footnote-counter fn))))))
1561 (incf markdown-footnote-counter))
1563 (defun markdown-footnote-new ()
1564 "Insert a footnote with a new number and jump to a position to enter the
1565 footnote text."
1566 (interactive)
1567 (let ((fn (markdown-footnote-counter-inc)))
1568 (insert (format "[^%d]" fn))
1569 (markdown-footnote-text-find-new-location)
1570 (insert (format "[^%d]: " fn))))
1572 (defun markdown-footnote-text-find-new-location ()
1573 "Position the cursor at the proper location for a new footnote text."
1574 (cond
1575 ((eq markdown-footnote-location 'end) (goto-char (point-max)))
1576 ((eq markdown-footnote-location 'immediately) (forward-paragraph))
1577 ((eq markdown-footnote-location 'header)
1578 ;; search for a header. if none is found, go to the end of the document.
1579 (catch 'eof
1580 (while (progn
1581 (forward-paragraph)
1582 (unless (re-search-forward markdown-regex-header nil t)
1583 (throw 'eof nil))
1584 (backward-paragraph)
1585 (forward-line)
1586 (not (looking-at markdown-regex-header)))))))
1587 (forward-line -1)
1588 ;; make sure we're on an empty line:
1589 (unless (markdown-cur-line-blank-p)
1590 (insert "\n"))
1591 ;; and make sure the previous line is empty:
1592 (unless (markdown-prev-line-blank-p)
1593 (insert "\n"))
1594 ;; then make sure there's an empty line following the footnote:
1595 (unless (markdown-next-line-blank-p)
1596 (insert "\n")
1597 (forward-line -1)))
1599 (defun markdown-footnote-kill ()
1600 "Kill the footnote at point.
1601 The footnote text is killed (and added to the kill ring), the
1602 footnote marker is deleted. Point has to be either at the
1603 footnote marker or in the footnote text."
1604 (interactive)
1605 (let (return-pos)
1606 (when (markdown-footnote-text-positions) ; if we're in a footnote text
1607 (markdown-footnote-return) ; we first move to the marker
1608 (setq return-pos 'text)) ; and remember our return position
1609 (let ((marker (markdown-footnote-delete-marker)))
1610 (unless marker
1611 (error "Not at a footnote"))
1612 (let ((text-pos (markdown-footnote-find-text (car marker))))
1613 (unless text-pos
1614 (error "No text for footnote `%s'" (car marker)))
1615 (goto-char text-pos)
1616 (let ((pos (markdown-footnote-kill-text)))
1617 (setq return-pos
1618 (if (and pos (eq return-pos 'text))
1620 (cadr marker))))))
1621 (goto-char return-pos)))
1623 (defun markdown-footnote-delete-marker ()
1624 "Delete a footnote marker at point.
1625 Returns a list (ID START) containing the footnote ID and the
1626 start position of the marker before deletion. If no footnote
1627 marker was deleted, this function returns NIL."
1628 (let ((marker (markdown-footnote-marker-positions)))
1629 (when marker
1630 (delete-region (second marker) (third marker))
1631 (butlast marker))))
1633 (defun markdown-footnote-kill-text ()
1634 "Kill footnote text at point.
1635 Returns the start position of the footnote text before deletion,
1636 or NIL if point was not inside a footnote text.
1638 The killed text is placed in the kill ring (without the footnote
1639 number)."
1640 (let ((fn (markdown-footnote-text-positions)))
1641 (when fn
1642 (let ((text (delete-and-extract-region (second fn) (third fn))))
1643 (string-match (concat "\\[\\" (first fn) "\\]:[[:space:]]*\\(\\(.*\n?\\)*\\)") text)
1644 (kill-new (match-string 1 text))
1645 (second fn)))))
1647 (defun markdown-footnote-goto-text ()
1648 "Jump to the text of the footnote at point."
1649 (interactive)
1650 (let ((fn (car (markdown-footnote-marker-positions))))
1651 (unless fn
1652 (error "Not at a footnote marker"))
1653 (let ((new-pos (markdown-footnote-find-text fn)))
1654 (unless new-pos
1655 (error "No definition found for footnote `%s'" fn))
1656 (goto-char new-pos))))
1658 (defun markdown-footnote-return ()
1659 "Return from a footnote to its footnote number in the main text."
1660 (interactive)
1661 (let ((fn (save-excursion
1662 (car (markdown-footnote-text-positions)))))
1663 (unless fn
1664 (error "Not in a footnote"))
1665 (let ((new-pos (markdown-footnote-find-marker fn)))
1666 (unless new-pos
1667 (error "Footnote marker `%s' not found" fn))
1668 (goto-char new-pos))))
1670 (defun markdown-footnote-find-marker (id)
1671 "Find the location of the footnote marker with ID.
1672 The actual buffer position returned is the position directly
1673 following the marker's closing bracket. If no marker is found,
1674 NIL is returned."
1675 (save-excursion
1676 (goto-char (point-min))
1677 (when (re-search-forward (concat "\\[" id "\\]\\([^:]\\|\\'\\)") nil t)
1678 (skip-chars-backward "^]")
1679 (point))))
1681 (defun markdown-footnote-find-text (id)
1682 "Find the location of the text of footnote ID.
1683 The actual buffer position returned is the position of the first
1684 character of the text, after the footnote's identifier. If no
1685 footnote text is found, NIL is returned."
1686 (save-excursion
1687 (goto-char (point-min))
1688 (when (re-search-forward (concat "^\\[" id "\\]:") nil t)
1689 (skip-chars-forward "[:space:]")
1690 (point))))
1692 (defun markdown-footnote-marker-positions ()
1693 "Return the position and ID of the footnote marker point is on.
1694 The return value is a list (ID START END). If point is not on a
1695 footnote, NIL is returned."
1696 ;; first make sure we're at a footnote marker
1697 (if (or (looking-back (concat "\\[\\^" markdown-footnote-chars "*\\]?") (point-at-bol))
1698 (looking-at (concat "\\[?\\^" markdown-footnote-chars "*?\\]")))
1699 (save-excursion
1700 ;; move point between [ and ^:
1701 (if (looking-at "\\[")
1702 (forward-char 1)
1703 (skip-chars-backward "^["))
1704 (looking-at (concat "\\(\\^" markdown-footnote-chars "*?\\)\\]"))
1705 (list (match-string 1) (1- (match-beginning 1)) (1+ (match-end 1))))))
1707 (defun markdown-footnote-text-positions ()
1708 "Return the start and end positions of the footnote text point is in.
1709 The exact return value is a list of three elements: (ID START
1710 END). The start position is the position of the opening bracket
1711 of the footnote id. The end position is directly after the
1712 newline that ends the footnote. If point is not in a footnote,
1713 NIL is returned instead."
1714 (save-excursion
1715 (let ((fn (progn
1716 (backward-paragraph)
1717 ;; if we're in a multiparagraph footnote, we need to back up further
1718 (while (>= (markdown-next-line-indent) 4)
1719 (backward-paragraph))
1720 (forward-line)
1721 (if (looking-at (concat "^\\[\\(\\^" markdown-footnote-chars "*?\\)\\]:"))
1722 (list (match-string 1) (point))))))
1723 (when fn
1724 (while (progn
1725 (forward-paragraph)
1726 (>= (markdown-next-line-indent) 4)))
1727 (append fn (list (point)))))))
1729 ;;; Indentation ====================================================================
1731 (defun markdown-indent-find-next-position (cur-pos positions)
1732 "Return the position after the index of CUR-POS in POSITIONS."
1733 (while (and positions
1734 (not (equal cur-pos (car positions))))
1735 (setq positions (cdr positions)))
1736 (or (cadr positions) 0))
1738 (defun markdown-indent-line ()
1739 "Indent the current line using some heuristics.
1740 If the _previous_ command was either `markdown-enter-key' or
1741 `markdown-cycle', then we should cycle to the next
1742 reasonable indentation position. Otherwise, we could have been
1743 called directly by `markdown-enter-key', by an initial call of
1744 `markdown-cycle', or indirectly by `auto-fill-mode'. In
1745 these cases, indent to the default position."
1746 (interactive)
1747 (let ((positions (markdown-calc-indents))
1748 (cur-pos (current-column)))
1749 (if (not (equal this-command 'markdown-cycle))
1750 (indent-line-to (car positions))
1751 (setq positions (sort (delete-dups positions) '<))
1752 (indent-line-to
1753 (markdown-indent-find-next-position cur-pos positions)))))
1755 (defun markdown-calc-indents ()
1756 "Return a list of indentation columns to cycle through.
1757 The first element in the returned list should be considered the
1758 default indentation level."
1759 (let (pos prev-line-pos positions)
1761 ;; Previous line indent
1762 (setq prev-line-pos (markdown-prev-line-indent))
1763 (setq positions (cons prev-line-pos positions))
1765 ;; Previous non-list-marker indent
1766 (setq pos (markdown-prev-non-list-indent))
1767 (when pos
1768 (setq positions (cons pos positions))
1769 (setq positions (cons (+ pos tab-width) positions)))
1771 ;; Indentation of the previous line + tab-width
1772 (cond
1773 (prev-line-pos
1774 (setq positions (cons (+ prev-line-pos tab-width) positions)))
1776 (setq positions (cons tab-width positions))))
1778 ;; Indentation of the previous line - tab-width
1779 (if (and prev-line-pos
1780 (> prev-line-pos tab-width))
1781 (setq positions (cons (- prev-line-pos tab-width) positions)))
1783 ;; Indentation of preceeding list item
1784 (setq pos
1785 (save-excursion
1786 (forward-line -1)
1787 (catch 'break
1788 (while (not (equal (point) (point-min)))
1789 (forward-line -1)
1790 (goto-char (point-at-bol))
1791 (when (re-search-forward markdown-regex-list-indent (point-at-eol) t)
1792 (throw 'break (length (match-string 1)))))
1793 nil)))
1794 (if (and pos (not (eq pos prev-line-pos)))
1795 (setq positions (cons pos positions)))
1797 ;; First column
1798 (setq positions (cons 0 positions))
1800 (reverse positions)))
1802 (defun markdown-do-normal-return ()
1803 "Insert a newline and optionally indent the next line."
1804 (newline)
1805 (if markdown-indent-on-enter
1806 (funcall indent-line-function)))
1808 (defun markdown-enter-key ()
1809 "Handle RET according to context.
1810 If there is a wiki link at the point, follow it unless
1811 `markdown-follow-wiki-link-on-enter' is nil. Otherwise, process
1812 it in the usual way."
1813 (interactive)
1814 (if (and markdown-follow-wiki-link-on-enter (markdown-wiki-link-p))
1815 (markdown-follow-wiki-link-at-point)
1816 (markdown-do-normal-return)))
1818 (defun markdown-dedent-or-delete (arg)
1819 "Handle BACKSPACE by cycling through indentation points.
1820 When BACKSPACE is pressed, if there is only whitespace
1821 before the current point, then dedent the line one level.
1822 Otherwise, do normal delete by repeating
1823 `backward-delete-char-untabify' ARG times."
1824 (interactive "*p")
1825 (let ((cur-pos (current-column))
1826 (start-of-indention (save-excursion
1827 (back-to-indentation)
1828 (current-column))))
1829 (if (and (> cur-pos 0) (= cur-pos start-of-indention))
1830 (let ((result 0))
1831 (dolist (i (markdown-calc-indents))
1832 (when (< i cur-pos)
1833 (setq result (max result i))))
1834 (indent-line-to result))
1835 (backward-delete-char-untabify arg))))
1839 ;;; Keymap ====================================================================
1841 (defvar markdown-mode-map
1842 (let ((map (make-keymap)))
1843 ;; Element insertion
1844 (define-key map "\C-c\C-al" 'markdown-insert-link)
1845 (define-key map "\C-c\C-ar" 'markdown-insert-reference-link-dwim)
1846 (define-key map "\C-c\C-aw" 'markdown-insert-wiki-link)
1847 (define-key map "\C-c\C-ii" 'markdown-insert-image)
1848 (define-key map "\C-c\C-t1" 'markdown-insert-header-1)
1849 (define-key map "\C-c\C-t2" 'markdown-insert-header-2)
1850 (define-key map "\C-c\C-t3" 'markdown-insert-header-3)
1851 (define-key map "\C-c\C-t4" 'markdown-insert-header-4)
1852 (define-key map "\C-c\C-t5" 'markdown-insert-header-5)
1853 (define-key map "\C-c\C-t6" 'markdown-insert-header-6)
1854 (define-key map "\C-c\C-pb" 'markdown-insert-bold)
1855 (define-key map "\C-c\C-ss" 'markdown-insert-bold)
1856 (define-key map "\C-c\C-pi" 'markdown-insert-italic)
1857 (define-key map "\C-c\C-se" 'markdown-insert-italic)
1858 (define-key map "\C-c\C-pf" 'markdown-insert-code)
1859 (define-key map "\C-c\C-sc" 'markdown-insert-code)
1860 (define-key map "\C-c\C-sb" 'markdown-insert-blockquote)
1861 (define-key map "\C-c\C-s\C-b" 'markdown-blockquote-region)
1862 (define-key map "\C-c\C-sp" 'markdown-insert-pre)
1863 (define-key map "\C-c\C-s\C-p" 'markdown-pre-region)
1864 (define-key map "\C-c-" 'markdown-insert-hr)
1865 (define-key map "\C-c\C-tt" 'markdown-insert-title)
1866 (define-key map "\C-c\C-ts" 'markdown-insert-section)
1867 ;; Footnotes
1868 (define-key map "\C-c\C-fn" 'markdown-footnote-new)
1869 (define-key map "\C-c\C-fg" 'markdown-footnote-goto-text)
1870 (define-key map "\C-c\C-fb" 'markdown-footnote-return)
1871 (define-key map "\C-c\C-fk" 'markdown-footnote-kill)
1872 ;; Regular Link Following
1873 (define-key map "\C-c\C-o" 'markdown-follow-link-at-point)
1874 ;; WikiLink Following
1875 (define-key map "\C-c\C-w" 'markdown-follow-wiki-link-at-point)
1876 (define-key map "\M-n" 'markdown-next-wiki-link)
1877 (define-key map "\M-p" 'markdown-previous-wiki-link)
1878 ;; Indentation
1879 (define-key map "\C-m" 'markdown-enter-key)
1880 (define-key map (kbd "<backspace>") 'markdown-dedent-or-delete)
1881 ;; Visibility cycling
1882 (define-key map (kbd "<tab>") 'markdown-cycle)
1883 (define-key map (kbd "<S-iso-lefttab>") 'markdown-shifttab)
1884 (define-key map (kbd "<S-tab>") 'markdown-shifttab)
1885 (define-key map (kbd "<backtab>") 'markdown-shifttab)
1886 ;; Header navigation
1887 (define-key map (kbd "C-M-n") 'outline-next-visible-heading)
1888 (define-key map (kbd "C-M-p") 'outline-previous-visible-heading)
1889 (define-key map (kbd "C-M-f") 'outline-forward-same-level)
1890 (define-key map (kbd "C-M-b") 'outline-backward-same-level)
1891 (define-key map (kbd "C-M-u") 'outline-up-heading)
1892 ;; Markdown functions
1893 (define-key map "\C-c\C-cm" 'markdown-other-window)
1894 (define-key map "\C-c\C-cp" 'markdown-preview)
1895 (define-key map "\C-c\C-ce" 'markdown-export)
1896 (define-key map "\C-c\C-cv" 'markdown-export-and-preview)
1897 (define-key map "\C-c\C-co" 'markdown-open)
1898 (define-key map "\C-c\C-cw" 'markdown-kill-ring-save)
1899 ;; References
1900 (define-key map "\C-c\C-cc" 'markdown-check-refs)
1901 ;; Lists
1902 (define-key map "\C-c\C-cn" 'markdown-cleanup-list-numbers)
1903 map)
1904 "Keymap for Markdown major mode.")
1906 ;;; Menu ==================================================================
1908 (easy-menu-define markdown-mode-menu markdown-mode-map
1909 "Menu for Markdown mode"
1910 '("Markdown"
1911 ("Show/Hide"
1912 ["Cycle visibility" markdown-cycle (outline-on-heading-p)]
1913 ["Cycle global visibility" markdown-shifttab])
1914 "---"
1915 ["Compile" markdown-other-window]
1916 ["Preview" markdown-preview]
1917 ["Export" markdown-export]
1918 ["Export & View" markdown-export-and-preview]
1919 ["Open" markdown-open]
1920 ["Kill ring save" markdown-kill-ring-save]
1921 "---"
1922 ("Headers (setext)"
1923 ["Insert Title" markdown-insert-title]
1924 ["Insert Section" markdown-insert-section])
1925 ("Headers (atx)"
1926 ["First level" markdown-insert-header-1]
1927 ["Second level" markdown-insert-header-2]
1928 ["Third level" markdown-insert-header-3]
1929 ["Fourth level" markdown-insert-header-4]
1930 ["Fifth level" markdown-insert-header-5]
1931 ["Sixth level" markdown-insert-header-6])
1932 "---"
1933 ["Bold" markdown-insert-bold]
1934 ["Italic" markdown-insert-italic]
1935 ["Blockquote" markdown-insert-blockquote]
1936 ["Preformatted" markdown-insert-pre]
1937 ["Code" markdown-insert-code]
1938 "---"
1939 ["Insert inline link" markdown-insert-link]
1940 ["Insert reference link" markdown-insert-reference-link-dwim]
1941 ["Insert image" markdown-insert-image]
1942 ["Insert horizontal rule" markdown-insert-hr]
1943 "---"
1944 ("Footnotes"
1945 ["Insert footnote" markdown-footnote-new]
1946 ["Jump to footnote text" markdown-footnote-goto-text]
1947 ["Return from footnote" markdown-footnote-return])
1948 "---"
1949 ["Check references" markdown-check-refs]
1950 ["Clean up list numbering" markdown-cleanup-list-numbers]
1951 "---"
1952 ["Version" markdown-show-version]
1957 ;;; imenu =====================================================================
1959 (defun markdown-imenu-create-index ()
1960 (let* ((root '(nil . nil))
1961 cur-alist
1962 (cur-level 0)
1963 (empty-heading "-")
1964 (self-heading ".")
1965 hashes pos level heading)
1966 (save-excursion
1967 (goto-char (point-min))
1968 (while (re-search-forward markdown-regex-header (point-max) t)
1969 (cond
1970 ((setq heading (match-string-no-properties 1))
1971 (setq pos (match-beginning 1)
1972 level 1))
1973 ((setq heading (match-string-no-properties 3))
1974 (setq pos (match-beginning 3)
1975 level 2))
1976 ((setq hashes (match-string-no-properties 5))
1977 (setq heading (match-string-no-properties 6)
1978 pos (match-beginning 5)
1979 level (length hashes))))
1980 (let ((alist (list (cons heading pos))))
1981 (cond
1982 ((= cur-level level) ; new sibling
1983 (setcdr cur-alist alist)
1984 (setq cur-alist alist))
1985 ((< cur-level level) ; first child
1986 (dotimes (i (- level cur-level 1))
1987 (setq alist (list (cons empty-heading alist))))
1988 (if cur-alist
1989 (let* ((parent (car cur-alist))
1990 (self-pos (cdr parent)))
1991 (setcdr parent (cons (cons self-heading self-pos) alist)))
1992 (setcdr root alist)) ; primogenitor
1993 (setq cur-alist alist)
1994 (setq cur-level level))
1995 (t ; new sibling of an ancestor
1996 (let ((sibling-alist (last (cdr root))))
1997 (dotimes (i (1- level))
1998 (setq sibling-alist (last (cdar sibling-alist))))
1999 (setcdr sibling-alist alist)
2000 (setq cur-alist alist))
2001 (setq cur-level level)))))
2002 (cdr root))))
2004 ;;; References ================================================================
2006 ;;; Undefined reference checking code by Dmitry Dzhus <mail@sphinx.net.ru>.
2008 (defconst markdown-refcheck-buffer
2009 "*Undefined references for %buffer%*"
2010 "Pattern for name of buffer for listing undefined references.
2011 The string %buffer% will be replaced by the corresponding
2012 `markdown-mode' buffer name.")
2014 (defun markdown-has-reference-definition (reference)
2015 "Find out whether Markdown REFERENCE is defined.
2017 REFERENCE should include the square brackets, like [this]."
2018 (let ((reference (downcase reference)))
2019 (save-excursion
2020 (goto-char (point-min))
2021 (catch 'found
2022 (while (re-search-forward markdown-regex-reference-definition nil t)
2023 (when (string= reference (downcase (match-string-no-properties 1)))
2024 (throw 'found (match-string-no-properties 2))))))))
2026 (defun markdown-get-undefined-refs ()
2027 "Return a list of undefined Markdown references.
2029 Result is an alist of pairs (reference . occurencies), where
2030 occurencies is itself another alist of pairs (label .
2031 line-number).
2033 For example, an alist corresponding to [Nice editor][Emacs] at line 12,
2034 \[GNU Emacs][Emacs] at line 45 and [manual][elisp] at line 127 is
2035 \((\"[emacs]\" (\"[Nice editor]\" . 12) (\"[GNU Emacs]\" . 45)) (\"[elisp]\" (\"[manual]\" . 127)))."
2036 (let ((missing))
2037 (save-excursion
2038 (goto-char (point-min))
2039 (while
2040 (re-search-forward markdown-regex-link-reference nil t)
2041 (let* ((label (match-string-no-properties 1))
2042 (reference (match-string-no-properties 2))
2043 (target (downcase (if (string= reference "[]") label reference))))
2044 (unless (markdown-has-reference-definition target)
2045 (let ((entry (assoc target missing)))
2046 (if (not entry)
2047 (add-to-list 'missing (cons target
2048 (list (cons label (markdown-line-number-at-pos)))) t)
2049 (setcdr entry
2050 (append (cdr entry) (list (cons label (markdown-line-number-at-pos))))))))))
2051 missing)))
2053 (defun markdown-add-missing-ref-definition (ref buffer &optional recheck)
2054 "Add blank REF definition to the end of BUFFER.
2056 REF is a Markdown reference in square brackets, like \"[lisp-history]\".
2058 When RECHECK is non-nil, BUFFER gets rechecked for undefined
2059 references so that REF disappears from the list of those links."
2060 (with-current-buffer buffer
2061 (when (not (eq major-mode 'markdown-mode))
2062 (error "Not available in current mode"))
2063 (goto-char (point-max))
2064 (indent-new-comment-line)
2065 (insert (concat ref ": ")))
2066 (switch-to-buffer-other-window buffer)
2067 (goto-char (point-max))
2068 (when recheck
2069 (markdown-check-refs t)))
2071 ;; Button which adds an empty Markdown reference definition to the end
2072 ;; of buffer specified as its 'target-buffer property. Reference name
2073 ;; is button's label
2074 (when (>= emacs-major-version 22)
2075 (define-button-type 'markdown-ref-button
2076 'help-echo "Push to create an empty reference definition"
2077 'face 'bold
2078 'action (lambda (b)
2079 (markdown-add-missing-ref-definition
2080 (button-label b) (button-get b 'target-buffer) t))))
2082 ;; Button jumping to line in buffer specified as its 'target-buffer
2083 ;; property. Line number is button's 'line property.
2084 (when (>= emacs-major-version 22)
2085 (define-button-type 'goto-line-button
2086 'help-echo "Push to go to this line"
2087 'face 'italic
2088 'action (lambda (b)
2089 (message (button-get b 'buffer))
2090 (switch-to-buffer-other-window (button-get b 'target-buffer))
2091 ;; use call-interactively to silence compiler
2092 (call-interactively 'goto-line (button-get b 'target-line)))))
2094 (defun markdown-check-refs (&optional silent)
2095 "Show all undefined Markdown references in current `markdown-mode' buffer.
2097 If SILENT is non-nil, do not message anything when no undefined
2098 references found.
2100 Links which have empty reference definitions are considered to be
2101 defined."
2102 (interactive "P")
2103 (when (not (eq major-mode 'markdown-mode))
2104 (error "Not available in current mode"))
2105 (let ((oldbuf (current-buffer))
2106 (refs (markdown-get-undefined-refs))
2107 (refbuf (get-buffer-create (markdown-replace-regexp-in-string
2108 "%buffer%" (buffer-name)
2109 markdown-refcheck-buffer))))
2110 (if (null refs)
2111 (progn
2112 (when (not silent)
2113 (message "No undefined references found"))
2114 (kill-buffer refbuf))
2115 (with-current-buffer refbuf
2116 (when view-mode
2117 (View-exit-and-edit))
2118 (erase-buffer)
2119 (insert "Following references lack definitions:")
2120 (newline 2)
2121 (dolist (ref refs)
2122 (let ((button-label (format "%s" (car ref))))
2123 (if (>= emacs-major-version 22)
2124 ;; Create a reference button in Emacs 22
2125 (insert-text-button button-label
2126 :type 'markdown-ref-button
2127 'target-buffer oldbuf)
2128 ;; Insert reference as text in Emacs < 22
2129 (insert button-label)))
2130 (insert " (")
2131 (dolist (occurency (cdr ref))
2132 (let ((line (cdr occurency)))
2133 (if (>= emacs-major-version 22)
2134 ;; Create a line number button in Emacs 22
2135 (insert-button (number-to-string line)
2136 :type 'goto-line-button
2137 'target-buffer oldbuf
2138 'target-line line)
2139 ;; Insert line number as text in Emacs < 22
2140 (insert (number-to-string line)))
2141 (insert " "))) (delete-char -1)
2142 (insert ")")
2143 (newline))
2144 (view-buffer-other-window refbuf)
2145 (goto-char (point-min))
2146 (forward-line 2)))))
2149 ;;; Lists =====================================================================
2151 (defun markdown--cleanup-list-numbers-level (&optional pfx)
2152 "Update the numbering for level PFX (as a string of spaces).
2154 Assume that the previously found match was for a numbered item in
2155 a list."
2156 (let ((cpfx pfx)
2157 (idx 0)
2158 (continue t)
2159 (step t)
2160 (sep nil))
2161 (while (and continue (not (eobp)))
2162 (setq step t)
2163 (cond
2164 ((looking-at "^\\([\s-]*\\)[0-9]+\\. ")
2165 (setq cpfx (match-string-no-properties 1))
2166 (cond
2167 ((string= cpfx pfx)
2168 (replace-match
2169 (concat pfx (number-to-string (setq idx (1+ idx))) ". "))
2170 (setq sep nil))
2171 ;; indented a level
2172 ((string< pfx cpfx)
2173 (setq sep (markdown--cleanup-list-numbers-level cpfx))
2174 (setq step nil))
2175 ;; exit the loop
2177 (setq step nil)
2178 (setq continue nil))))
2180 ((looking-at "^\\([\s-]*\\)[^ \n\r].*$")
2181 (setq cpfx (match-string-no-properties 1))
2182 (cond
2183 ;; reset if separated before
2184 ((string= cpfx pfx) (when sep (setq idx 0)))
2185 ((string< cpfx pfx)
2186 (setq step nil)
2187 (setq continue nil))))
2188 (t (setq sep t)))
2190 (when step
2191 (beginning-of-line)
2192 (setq continue (= (forward-line) 0))))
2193 sep))
2195 ;;;###autoload
2196 (defun markdown-cleanup-list-numbers ()
2197 "Update the numbering of ordered lists."
2198 (interactive)
2199 (save-excursion
2200 (goto-char (point-min))
2201 (markdown--cleanup-list-numbers-level "")))
2204 ;;; Outline ===================================================================
2206 ;; The following visibility cycling code was taken from org-mode
2207 ;; by Carsten Dominik and adapted for markdown-mode.
2209 (defvar markdown-cycle-global-status 1)
2210 (defvar markdown-cycle-subtree-status nil)
2212 ;; Based on org-end-of-subtree from org.el
2213 (defun markdown-end-of-subtree (&optional invisible-OK)
2214 "Move to the end of the current subtree.
2215 Only visible heading lines are considered, unless INVISIBLE-OK is
2216 non-nil."
2217 (outline-back-to-heading invisible-OK)
2218 (let ((first t)
2219 (level (funcall outline-level)))
2220 (while (and (not (eobp))
2221 (or first (> (funcall outline-level) level)))
2222 (setq first nil)
2223 (outline-next-heading))
2224 (if (memq (preceding-char) '(?\n ?\^M))
2225 (progn
2226 ;; Go to end of line before heading
2227 (forward-char -1)
2228 (if (memq (preceding-char) '(?\n ?\^M))
2229 ;; leave blank line before heading
2230 (forward-char -1)))))
2231 (point))
2233 ;; Based on org-cycle from org.el.
2234 (defun markdown-cycle (&optional arg)
2235 "Visibility cycling for Markdown mode.
2236 If ARG is t, perform global visibility cycling. If the point is
2237 at an atx-style header, cycle visibility of the corresponding
2238 subtree. Otherwise, insert a tab using `indent-relative'."
2239 (interactive "P")
2240 (cond
2241 ((eq arg t) ;; Global cycling
2242 (cond
2243 ((and (eq last-command this-command)
2244 (eq markdown-cycle-global-status 2))
2245 ;; Move from overview to contents
2246 (hide-sublevels 1)
2247 (message "CONTENTS")
2248 (setq markdown-cycle-global-status 3))
2250 ((and (eq last-command this-command)
2251 (eq markdown-cycle-global-status 3))
2252 ;; Move from contents to all
2253 (show-all)
2254 (message "SHOW ALL")
2255 (setq markdown-cycle-global-status 1))
2258 ;; Defaults to overview
2259 (hide-body)
2260 (message "OVERVIEW")
2261 (setq markdown-cycle-global-status 2))))
2263 ((save-excursion (beginning-of-line 1) (looking-at outline-regexp))
2264 ;; At a heading: rotate between three different views
2265 (outline-back-to-heading)
2266 (let ((goal-column 0) eoh eol eos)
2267 ;; Determine boundaries
2268 (save-excursion
2269 (outline-back-to-heading)
2270 (save-excursion
2271 (beginning-of-line 2)
2272 (while (and (not (eobp)) ;; this is like `next-line'
2273 (get-char-property (1- (point)) 'invisible))
2274 (beginning-of-line 2)) (setq eol (point)))
2275 (outline-end-of-heading) (setq eoh (point))
2276 (markdown-end-of-subtree t)
2277 (skip-chars-forward " \t\n")
2278 (beginning-of-line 1) ; in case this is an item
2279 (setq eos (1- (point))))
2280 ;; Find out what to do next and set `this-command'
2281 (cond
2282 ((= eos eoh)
2283 ;; Nothing is hidden behind this heading
2284 (message "EMPTY ENTRY")
2285 (setq markdown-cycle-subtree-status nil))
2286 ((>= eol eos)
2287 ;; Entire subtree is hidden in one line: open it
2288 (show-entry)
2289 (show-children)
2290 (message "CHILDREN")
2291 (setq markdown-cycle-subtree-status 'children))
2292 ((and (eq last-command this-command)
2293 (eq markdown-cycle-subtree-status 'children))
2294 ;; We just showed the children, now show everything.
2295 (show-subtree)
2296 (message "SUBTREE")
2297 (setq markdown-cycle-subtree-status 'subtree))
2299 ;; Default action: hide the subtree.
2300 (hide-subtree)
2301 (message "FOLDED")
2302 (setq markdown-cycle-subtree-status 'folded)))))
2305 (indent-for-tab-command))))
2307 ;; Based on org-shifttab from org.el.
2308 (defun markdown-shifttab ()
2309 "Global visibility cycling.
2310 Calls `markdown-cycle' with argument t."
2311 (interactive)
2312 (markdown-cycle t))
2314 (defun markdown-outline-level ()
2315 "Return the depth to which a statement is nested in the outline."
2316 (cond
2317 ((match-end 1) 1)
2318 ((match-end 2) 2)
2319 ((- (match-end 0) (match-beginning 0)))))
2321 ;;; Commands ==================================================================
2323 (defun markdown (&optional output-buffer-name)
2324 "Run `markdown' on current buffer and insert output in buffer given by
2325 `output-buffer-name' (defaults to `markdown-output-buffer-name'). Return the
2326 OUTPUT-BUFFER used."
2327 (interactive)
2328 (save-window-excursion
2329 (let ((begin-region)
2330 (end-region))
2331 (if (markdown-transient-mark-mode-active)
2332 (setq begin-region (region-beginning)
2333 end-region (region-end))
2334 (setq begin-region (point-min)
2335 end-region (point-max)))
2337 (unless output-buffer-name
2338 (setq output-buffer-name markdown-output-buffer-name))
2340 (cond
2341 ;; Handle case when `markdown-command' does not read from stdin
2342 (markdown-command-needs-filename
2343 (if (not buffer-file-name)
2344 (error "Must be visiting a file")
2345 (shell-command (concat markdown-command " "
2346 (shell-quote-argument buffer-file-name))
2347 output-buffer-name)))
2348 ;; Pass region to `markdown-command' via stdin
2350 (shell-command-on-region begin-region end-region markdown-command
2351 output-buffer-name))))
2352 output-buffer-name))
2354 (defun markdown-standalone (&optional output-buffer-name)
2355 "special function to provide html standalone output"
2356 (interactive)
2357 (setq output-buffer-name (markdown output-buffer-name))
2358 (with-current-buffer output-buffer-name
2359 (set-buffer output-buffer-name)
2360 (goto-char (point-min))
2361 (unless (markdown-output-standalone-p)
2362 (markdown-add-xhtml-header-and-footer output-buffer-name))
2363 (html-mode))
2364 output-buffer-name)
2366 (defun markdown-other-window (&optional output-buffer-name)
2367 " Run `markdown' on current buffer and display in other window"
2368 (interactive)
2369 (display-buffer (markdown-standalone output-buffer-name)))
2371 (defun markdown-output-standalone-p ()
2372 "Determine whether `markdown-command' output is standalone XHTML.
2373 Standalone XHTML output is identified by an occurrence of
2374 `markdown-xhtml-standalone-regexp' in the first five lines of output."
2375 (re-search-forward
2376 markdown-xhtml-standalone-regexp
2377 (save-excursion (goto-char (point-min)) (forward-line 4) (point))
2380 (defun markdown-add-xhtml-header-and-footer (title)
2381 "Wrap XHTML header and footer with given TITLE around current buffer."
2382 (insert "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"
2383 "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"\n"
2384 "\t\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n\n"
2385 "<html xmlns=\"http://www.w3.org/1999/xhtml\">\n\n"
2386 "<head>\n<title>")
2387 (insert title)
2388 (insert "</title>\n")
2389 (when (> (length markdown-content-type) 0)
2390 (insert
2391 (format
2392 "<meta http-equiv=\"Content-Type\" content=\"%s;charset=%s\"/>\n"
2393 markdown-content-type
2394 (or (and markdown-coding-system
2395 (fboundp 'coding-system-get)
2396 (coding-system-get markdown-coding-system
2397 'mime-charset))
2398 (and (fboundp 'coding-system-get)
2399 (coding-system-get buffer-file-coding-system
2400 'mime-charset))
2401 "iso-8859-1"))))
2402 (if (> (length markdown-css-path) 0)
2403 (insert "<link rel=\"stylesheet\" type=\"text/css\" media=\"all\" href=\""
2404 markdown-css-path
2405 "\" />\n"))
2406 (when (> (length markdown-xhtml-header-content) 0)
2407 (insert markdown-xhtml-header-content))
2408 (insert "\n</head>\n\n"
2409 "<body>\n\n")
2410 (goto-char (point-max))
2411 (insert "\n"
2412 "</body>\n"
2413 "</html>\n"))
2415 (defun markdown-preview (&optional output-buffer-name)
2416 "Run `markdown' on the current buffer and preview the output in a browser."
2417 (interactive)
2418 (browse-url-of-buffer (markdown markdown-output-buffer-name)))
2420 (defun markdown-export-file-name (&optional extension)
2421 "Attempt to generate a filename for Markdown output.
2422 If the current buffer is visiting a file, we construct a new
2423 output filename based on that filename. Otherwise, return nil."
2424 (when (buffer-file-name)
2425 (unless extension
2426 (setq extension ".html"))
2427 (concat
2428 (cond
2429 ((buffer-file-name)
2430 (file-name-sans-extension (buffer-file-name)))
2431 (t (buffer-name)))
2432 extension)))
2434 (defun markdown-export (&optional output-file)
2435 "Run Markdown on the current buffer, save to a file, and return the filename.
2436 The resulting filename will be constructed using the current filename, but
2437 with the extension removed and replaced with .html."
2438 (interactive)
2439 (unless output-file
2440 (setq output-file (markdown-export-file-name ".html")))
2441 (when output-file
2442 (let ((output-buffer-name))
2443 (setq output-buffer-name (buffer-name (find-file-noselect output-file)))
2444 (markdown-standalone output-buffer-name)
2445 (with-current-buffer output-buffer-name
2446 (save-buffer))
2447 output-file)))
2449 (defun markdown-export-and-preview ()
2450 "Export to XHTML using `markdown-export' and browse the resulting file."
2451 (interactive)
2452 (browse-url (markdown-export)))
2454 (defun markdown-open ()
2455 "Open file for the current buffer with `markdown-open-command'."
2456 (interactive)
2457 (if (not markdown-open-command)
2458 (error "Variable `markdown-open-command' must be set")
2459 (if (not buffer-file-name)
2460 (error "Must be visiting a file")
2461 (call-process markdown-open-command
2462 nil nil nil buffer-file-name))))
2464 (defun markdown-kill-ring-save ()
2465 "Run Markdown on file and store output in the kill ring."
2466 (interactive)
2467 (save-window-excursion
2468 (markdown)
2469 (with-current-buffer markdown-output-buffer-name
2470 (kill-ring-save (point-min) (point-max)))))
2473 ;;; Links =====================================================================
2475 (require 'thingatpt)
2477 (defun markdown-link-p ()
2478 "Return non-nil when `point' is at a non-wiki link.
2479 See `markdown-wiki-link-p' for more information."
2480 (let ((case-fold-search nil))
2481 (and (not (markdown-wiki-link-p))
2482 (or (thing-at-point-looking-at markdown-regex-link-inline)
2483 (thing-at-point-looking-at markdown-regex-link-reference)
2484 (thing-at-point-looking-at markdown-regex-uri)
2485 (thing-at-point-looking-at markdown-regex-angle-uri)))))
2487 (defun markdown-link-link ()
2488 "Return the link part of the regular (non-wiki) link at point.
2489 Works with both inline and reference style links. If point is
2490 not at a link or the link reference is not defined returns nil."
2491 (cond
2492 ((thing-at-point-looking-at markdown-regex-link-inline)
2493 (substring-no-properties (match-string 2) 1 -1))
2494 ((thing-at-point-looking-at markdown-regex-link-reference)
2495 (let* ((label (match-string-no-properties 1))
2496 (reference (match-string-no-properties 2))
2497 (target (downcase (if (string= reference "[]") label reference))))
2498 (markdown-has-reference-definition target)))
2499 ((thing-at-point-looking-at markdown-regex-uri)
2500 (match-string-no-properties 0))
2501 ((thing-at-point-looking-at markdown-regex-angle-uri)
2502 (match-string-no-properties 2))
2503 (t nil)))
2505 (defun markdown-follow-link-at-point ()
2506 "Open the current non-wiki link in a browser."
2507 (interactive)
2508 (if (markdown-link-p) (browse-url (markdown-link-link))
2509 (error "Point is not at a Markdown link or URI")))
2512 ;;; WikiLink Following/Markup =================================================
2514 (defun markdown-wiki-link-p ()
2515 "Return non-nil when `point' is at a true wiki link.
2516 A true wiki link name matches `markdown-regex-wiki-link' but does not
2517 match the current file name after conversion. This modifies the data
2518 returned by `match-data'. Note that the potential wiki link name must
2519 be available via `match-string'."
2520 (let ((case-fold-search nil))
2521 (and (thing-at-point-looking-at markdown-regex-wiki-link)
2522 (or (not buffer-file-name)
2523 (not (string-equal (buffer-file-name)
2524 (markdown-convert-wiki-link-to-filename
2525 (markdown-wiki-link-link)))))
2526 (not (save-match-data
2527 (save-excursion))))))
2529 (defun markdown-wiki-link-link ()
2530 "Return the link part of the wiki link using current match data.
2531 The location of the link component depends on the value of
2532 `markdown-wiki-link-alias-first'."
2533 (if markdown-wiki-link-alias-first
2534 (or (match-string 3) (match-string 1))
2535 (match-string 1)))
2537 (defun markdown-convert-wiki-link-to-filename (name)
2538 "Generate a filename from the wiki link NAME.
2539 Spaces in NAME are replaced with `markdown-link-space-sub-char'.
2540 When in `gfm-mode', follow GitHub's conventions where [[Test Test]]
2541 and [[test test]] both map to Test-test.ext."
2542 (let ((basename (markdown-replace-regexp-in-string
2543 "[[:space:]\n]" markdown-link-space-sub-char name)))
2544 (when (eq major-mode 'gfm-mode)
2545 (setq basename (concat (upcase (substring basename 0 1))
2546 (downcase (substring basename 1 nil)))))
2547 (concat basename
2548 (if (buffer-file-name)
2549 (concat "."
2550 (file-name-extension (buffer-file-name)))))))
2552 (defun markdown-follow-wiki-link (name &optional other)
2553 "Follow the wiki link NAME.
2554 Convert the name to a file name and call `find-file'. Ensure that
2555 the new buffer remains in `markdown-mode'."
2556 (let ((filename (markdown-convert-wiki-link-to-filename name))
2557 (wp (file-name-directory buffer-file-name)))
2558 (when other (other-window 1))
2559 (find-file (concat wp filename)))
2560 (when (not (eq major-mode 'markdown-mode))
2561 (markdown-mode)))
2563 (defun markdown-follow-wiki-link-at-point (&optional arg)
2564 "Find Wiki Link at point.
2565 With prefix argument C-u open the file in other window.
2567 See `markdown-wiki-link-p' and `markdown-follow-wiki-link'."
2568 (interactive "P")
2569 (if (markdown-wiki-link-p)
2570 (markdown-follow-wiki-link (markdown-wiki-link-link) arg)
2571 (error "Point is not at a Wiki Link")))
2573 (defun markdown-next-wiki-link ()
2574 "Jump to next wiki link.
2575 See `markdown-wiki-link-p'."
2576 (interactive)
2577 (if (markdown-wiki-link-p)
2578 ;; At a wiki link already, move past it.
2579 (goto-char (+ 1 (match-end 0))))
2580 (save-match-data
2581 ;; Search for the next wiki link and move to the beginning.
2582 (re-search-forward markdown-regex-wiki-link nil t)
2583 (goto-char (match-beginning 0))))
2585 (defun markdown-previous-wiki-link ()
2586 "Jump to previous wiki link.
2587 See `markdown-wiki-link-p'."
2588 (interactive)
2589 (re-search-backward markdown-regex-wiki-link nil t))
2591 (defun markdown-highlight-wiki-link (from to face)
2592 "Highlight the wiki link in the region between FROM and TO using FACE."
2593 (put-text-property from to 'font-lock-face face))
2595 (defun markdown-unfontify-region-wiki-links (from to)
2596 "Remove wiki link faces from the region specified by FROM and TO."
2597 (interactive "nfrom: \nnto: ")
2598 (remove-text-properties from to '(font-lock-face markdown-link-face))
2599 (remove-text-properties from to '(font-lock-face markdown-missing-link-face)))
2601 (defun markdown-fontify-region-wiki-links (from to)
2602 "Search region given by FROM and TO for wiki links and fontify them.
2603 If a wiki link is found check to see if the backing file exists
2604 and highlight accordingly."
2605 (goto-char from)
2606 (save-match-data
2607 (while (re-search-forward markdown-regex-wiki-link to t)
2608 (let ((highlight-beginning (match-beginning 0))
2609 (highlight-end (match-end 0))
2610 (file-name
2611 (markdown-convert-wiki-link-to-filename (match-string 1))))
2612 (if (file-exists-p file-name)
2613 (markdown-highlight-wiki-link
2614 highlight-beginning highlight-end markdown-link-face)
2615 (markdown-highlight-wiki-link
2616 highlight-beginning highlight-end markdown-link-face)
2617 (markdown-highlight-wiki-link
2618 highlight-beginning highlight-end markdown-missing-link-face))))))
2620 (defun markdown-extend-changed-region (from to)
2621 "Extend region given by FROM and TO so that we can fontify all links.
2622 The region is extended to the first newline before and the first
2623 newline after."
2624 ;; start looking for the first new line before 'from
2625 (goto-char from)
2626 (re-search-backward "\n" nil t)
2627 (let ((new-from (point-min))
2628 (new-to (point-max)))
2629 (if (not (= (point) from))
2630 (setq new-from (point)))
2631 ;; do the same thing for the first new line after 'to
2632 (goto-char to)
2633 (re-search-forward "\n" nil t)
2634 (if (not (= (point) to))
2635 (setq new-to (point)))
2636 (values new-from new-to)))
2638 (defun markdown-check-change-for-wiki-link (from to change)
2639 "Check region between FROM and TO for wiki links and re-fontfy as needed.
2640 Designed to be used with the `after-change-functions' hook.
2641 CHANGE is the number of bytes of pre-change text replaced by the
2642 given range."
2643 (interactive "nfrom: \nnto: \nnchange: ")
2644 (let* ((modified (buffer-modified-p))
2645 (buffer-undo-list t)
2646 (inhibit-read-only t)
2647 (inhibit-point-motion-hooks t)
2648 deactivate-mark
2649 buffer-file-truename)
2650 (unwind-protect
2651 (save-excursion
2652 (save-match-data
2653 (save-restriction
2654 ;; Extend the region to fontify so that it starts
2655 ;; and ends at safe places.
2656 (multiple-value-bind (new-from new-to)
2657 (markdown-extend-changed-region from to)
2658 ;; Unfontify existing fontification (start from scratch)
2659 (markdown-unfontify-region-wiki-links new-from new-to)
2660 ;; Now do the fontification.
2661 (markdown-fontify-region-wiki-links new-from new-to)))))
2662 (and (not modified)
2663 (buffer-modified-p)
2664 (set-buffer-modified-p nil)))))
2666 (defun markdown-fontify-buffer-wiki-links ()
2667 "Refontify all wiki links in the buffer."
2668 (interactive)
2669 (markdown-check-change-for-wiki-link (point-min) (point-max) 0))
2671 ;;; Miscellaneous =============================================================
2673 (defun markdown-line-number-at-pos (&optional pos)
2674 "Return (narrowed) buffer line number at position POS.
2675 If POS is nil, use current buffer location.
2676 This is an exact copy of `line-number-at-pos' for use in emacs21."
2677 (let ((opoint (or pos (point))) start)
2678 (save-excursion
2679 (goto-char (point-min))
2680 (setq start (point))
2681 (goto-char opoint)
2682 (forward-line 0)
2683 (1+ (count-lines start (point))))))
2685 (defun markdown-nobreak-p ()
2686 "Return nil if it is acceptable to break the current line at the point."
2687 ;; inside in square brackets (e.g., link anchor text)
2688 (looking-back "\\[[^]]*"))
2692 ;;; Mode definition ==========================================================
2694 (defun markdown-show-version ()
2695 "Show the version number in the minibuffer."
2696 (interactive)
2697 (message "markdown-mode, version %s" markdown-mode-version))
2699 ;;;###autoload
2700 (define-derived-mode markdown-mode text-mode "Markdown"
2701 "Major mode for editing Markdown files."
2702 ;; Natural Markdown tab width
2703 (setq tab-width 4)
2704 ;; Comments
2705 (make-local-variable 'comment-start)
2706 (setq comment-start "<!-- ")
2707 (make-local-variable 'comment-end)
2708 (setq comment-end " -->")
2709 (make-local-variable 'comment-start-skip)
2710 (setq comment-start-skip "<!--[ \t]*")
2711 (make-local-variable 'comment-column)
2712 (setq comment-column 0)
2713 ;; Font lock.
2714 (set (make-local-variable 'font-lock-defaults)
2715 '(markdown-mode-font-lock-keywords))
2716 (set (make-local-variable 'font-lock-multiline) t)
2717 ;; For imenu support
2718 (setq imenu-create-index-function 'markdown-imenu-create-index)
2719 ;; For menu support in XEmacs
2720 (easy-menu-add markdown-mode-menu markdown-mode-map)
2721 (set (make-local-variable 'beginning-of-defun-function)
2722 'markdown-beginning-of-defun)
2723 (set (make-local-variable 'end-of-defun-function) 'markdown-end-of-defun)
2724 ;; Make filling work with lists (unordered, ordered, and definition)
2725 (set (make-local-variable 'paragraph-start)
2726 "\f\\|[ \t]*$\\|^[ \t]*[*+-] \\|^[ \t]*[0-9]+\\.\\|^[ \t]*: ")
2727 ;; Outline mode
2728 (make-local-variable 'outline-regexp)
2729 (setq outline-regexp markdown-regex-header)
2730 (make-local-variable 'outline-level)
2731 (setq outline-level 'markdown-outline-level)
2732 ;; Cause use of ellipses for invisible text.
2733 (add-to-invisibility-spec '(outline . t))
2734 ;; Indentation and filling
2735 (make-local-variable 'fill-nobreak-predicate)
2736 (add-hook 'fill-nobreak-predicate 'markdown-nobreak-p)
2737 (setq indent-line-function markdown-indent-function)
2739 ;; Prepare hooks for XEmacs compatibility
2740 (when (featurep 'xemacs)
2741 (make-local-hook 'after-change-functions)
2742 (make-local-hook 'font-lock-extend-region-functions)
2743 (make-local-hook 'window-configuration-change-hook))
2745 ;; Multiline font lock
2746 (add-hook 'font-lock-extend-region-functions
2747 'markdown-font-lock-extend-region)
2749 ;; Anytime text changes make sure it gets fontified correctly
2750 (add-hook 'after-change-functions 'markdown-check-change-for-wiki-link t t)
2752 ;; If we left the buffer there is a really good chance we were
2753 ;; creating one of the wiki link documents. Make sure we get
2754 ;; refontified when we come back.
2755 (add-hook 'window-configuration-change-hook
2756 'markdown-fontify-buffer-wiki-links t t)
2758 ;; do the initial link fontification
2759 (markdown-fontify-buffer-wiki-links))
2761 ;;(add-to-list 'auto-mode-alist '("\\.text$" . markdown-mode))
2763 ;;; GitHub Flavored Markdown Mode ============================================
2765 ;;;###autoload
2766 (define-derived-mode gfm-mode markdown-mode "GFM"
2767 "Major mode for editing GitHub Flavored Markdown files."
2768 (setq markdown-link-space-sub-char "-")
2769 (auto-fill-mode 0)
2770 ;; Use visual-line-mode if available, fall back to longlines-mode:
2771 (if (fboundp 'visual-line-mode)
2772 (visual-line-mode 1)
2773 (longlines-mode 1))
2774 ;; do the initial link fontification
2775 (markdown-fontify-buffer-wiki-links))
2778 (provide 'markdown-mode)
2780 ;;; markdown-mode.el ends here