Update language list
[markdown-mode.git] / markdown-mode.el
blobbad960d595b32ceb97e0f9fc415eccfcdda9952c
1 ;;; markdown-mode.el --- Emacs Major mode for Markdown-formatted text files
3 ;; Copyright (C) 2007-2016 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>
24 ;; Copyright (C) 2013 Matus Goljer <dota.keys@gmail.com>
25 ;; Copyright (C) 2015 Google, Inc. (Contributor: Samuel Freilich <sfreilich@google.com>)
26 ;; Copyright (C) 2015 Antonis Kanouras <antonis@metadosis.gr>
27 ;; Copyright (C) 2015 Howard Melman <hmelman@gmail.com>
28 ;; Copyright (C) 2015-2016 Danny McClanahan <danieldmcclanahan@gmail.com>
29 ;; Copyright (C) 2015-2016 Syohei Yoshida <syohex@gmail.com>
31 ;; Author: Jason R. Blevins <jrblevin@sdf.org>
32 ;; Maintainer: Jason R. Blevins <jrblevin@sdf.org>
33 ;; Created: May 24, 2007
34 ;; Version: 2.1
35 ;; Package-Requires: ((cl-lib "0.5"))
36 ;; Keywords: Markdown, GitHub Flavored Markdown, itex
37 ;; URL: http://jblevins.org/projects/markdown-mode/
39 ;; This file is not part of GNU Emacs.
41 ;; This program is free software; you can redistribute it and/or modify
42 ;; it under the terms of the GNU General Public License as published by
43 ;; the Free Software Foundation; either version 2, or (at your option)
44 ;; any later version.
46 ;; This program is distributed in the hope that it will be useful,
47 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
48 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
49 ;; GNU General Public License for more details.
51 ;; You should have received a copy of the GNU General Public License
52 ;; along with this program; if not, write to the Free Software
53 ;; Foundation, Inc., 51 Franklin Street, Fifth Floor,
54 ;; Boston, MA 02110-1301, USA.
56 ;;; Commentary:
58 ;; markdown-mode is a major mode for editing [Markdown][]-formatted
59 ;; text files in GNU Emacs. markdown-mode is free software, licensed
60 ;; under the GNU GPL.
62 ;; [Markdown]: http://daringfireball.net/projects/markdown/
64 ;; The latest stable version is markdown-mode 2.1, released on January 9, 2016:
66 ;; * [markdown-mode.el][]
67 ;; * [Screenshot][][^theme]
68 ;; * [Release notes][]
70 ;; [markdown-mode.el]: http://jblevins.org/projects/markdown-mode/markdown-mode.el
71 ;; [Screenshot]: http://jblevins.org/projects/markdown-mode/screenshots/20160108-001.png
72 ;; [Release notes]: http://jblevins.org/projects/markdown-mode/rev-2-1
74 ;; [^theme]: The theme used in the screenshot is
75 ;; [color-theme-twilight](https://github.com/crafterm/twilight-emacs).
77 ;; The latest development version can be obtained from the Git
78 ;; repository at <http://jblevins.org/git/markdown-mode.git> or from
79 ;; [GitHub][]:
81 ;; git clone git://jblevins.org/git/markdown-mode.git
82 ;; git clone https://github.com/jrblevin/markdown-mode.git
84 ;; [![Build Status][status]][travis]
86 ;; [devel.el]: http://jblevins.org/git/markdown-mode.git/plain/markdown-mode.el
87 ;; [GitHub]: https://github.com/jrblevin/markdown-mode/
88 ;; [travis]: https://travis-ci.org/jrblevin/markdown-mode
89 ;; [status]: https://travis-ci.org/jrblevin/markdown-mode.svg?branch=master
91 ;; markdown-mode is also available in several package managers, including:
93 ;; * Debian Linux: [elpa-markdown-mode][] and [emacs-goodies-el][]
94 ;; * Ubuntu Linux: [elpa-markdown-mode][elpa-ubuntu] and [emacs-goodies-el][emacs-goodies-el-ubuntu]
95 ;; * RedHat and Fedora Linux: [emacs-goodies][]
96 ;; * NetBSD: [textproc/markdown-mode][]
97 ;; * MacPorts: [markdown-mode.el][macports-package] ([pending][macports-ticket])
98 ;; * FreeBSD: [textproc/markdown-mode.el][freebsd-port]
100 ;; [elpa-markdown-mode]: https://packages.debian.org/sid/lisp/elpa-markdown-mode
101 ;; [elpa-ubuntu]: http://packages.ubuntu.com/search?keywords=elpa-markdown-mode
102 ;; [emacs-goodies-el]: http://packages.debian.org/emacs-goodies-el
103 ;; [emacs-goodies-el-ubuntu]: http://packages.ubuntu.com/search?keywords=emacs-goodies-el
104 ;; [emacs-goodies]: https://apps.fedoraproject.org/packages/emacs-goodies
105 ;; [textproc/markdown-mode]: http://pkgsrc.se/textproc/markdown-mode
106 ;; [macports-package]: https://trac.macports.org/browser/trunk/dports/editors/markdown-mode.el/Portfile
107 ;; [macports-ticket]: http://trac.macports.org/ticket/35716
108 ;; [freebsd-port]: http://svnweb.freebsd.org/ports/head/textproc/markdown-mode.el
110 ;;; Installation:
112 ;; Make sure to place `markdown-mode.el` somewhere in the load-path and add
113 ;; the following lines to your `.emacs` file to associate markdown-mode
114 ;; with `.text`, `.markdown`, and `.md` files:
116 ;; (autoload 'markdown-mode "markdown-mode"
117 ;; "Major mode for editing Markdown files" t)
118 ;; (add-to-list 'auto-mode-alist '("\\.text\\'" . markdown-mode))
119 ;; (add-to-list 'auto-mode-alist '("\\.markdown\\'" . markdown-mode))
120 ;; (add-to-list 'auto-mode-alist '("\\.md\\'" . markdown-mode))
122 ;; There is no official Markdown file extension, nor is there even a
123 ;; _de facto_ standard, so you can easily add, change, or remove any
124 ;; of the file extensions above as needed.
126 ;; `markdown-mode' depends on `cl-lib', which has been bundled with
127 ;; GNU Emacs since 24.3. Users of GNU Emacs 24.1 and 24.2 can install
128 ;; `cl-lib' with `package.el'.
130 ;;; Usage:
132 ;; Keybindings are grouped by prefixes based on their function. For
133 ;; example, the commands for inserting links are grouped under `C-c
134 ;; C-a`, where the `C-a` is a mnemonic for the HTML `<a>` tag. In
135 ;; other cases, the connection to HTML is not direct. For example,
136 ;; commands dealing with headings begin with `C-c C-t` (mnemonic:
137 ;; titling). The primary commands in each group will are described
138 ;; below. You can obtain a list of all keybindings by pressing `C-c
139 ;; C-h`. Movement and shifting commands tend to be associated with
140 ;; paired delimiters such as `M-{` and `M-}` or `C-c <` and `C-c >`.
141 ;; Outline navigation keybindings the same as in `org-mode'. Finally,
142 ;; commands for running Markdown or doing maintenance on an open file
143 ;; are grouped under the `C-c C-c` prefix. The most commonly used
144 ;; commands are described below. You can obtain a list of all
145 ;; keybindings by pressing `C-c C-h`.
147 ;; * Hyperlinks: `C-c C-a`
149 ;; In this group, `C-c C-a l` inserts an inline link of the form
150 ;; `[text](url)`. The link text is determined as follows. First,
151 ;; if there is an active region (i.e., when transient mark mode is
152 ;; on and the mark is active), use it as the link text. Second,
153 ;; if the point is at a word, use that word as the link text. In
154 ;; these two cases, the original text will be replaced with the
155 ;; link and point will be left at the position for inserting a
156 ;; URL. Otherwise, insert empty link markup and place the point
157 ;; for inserting the link text.
159 ;; `C-c C-a L` inserts a reference link of the form `[text][label]`
160 ;; and, optionally, a corresponding reference label definition.
161 ;; The link text is determined in the same way as with an inline
162 ;; link (using the region, when active, or the word at the point),
163 ;; but instead of inserting empty markup as a last resort, the
164 ;; link text will be read from the minibuffer. The reference
165 ;; label will be read from the minibuffer in both cases, with
166 ;; completion from the set of currently defined references. To
167 ;; create an implicit reference link, press `RET` to accept the
168 ;; default, an empty label. If the entered referenced label is
169 ;; not defined, additionally prompt for the URL and (optional)
170 ;; title. If a URL is provided, a reference definition will be
171 ;; inserted in accordance with `markdown-reference-location'.
172 ;; If a title is given, it will be added to the end of the
173 ;; reference definition and will be used to populate the title
174 ;; attribute when converted to XHTML.
176 ;; `C-c C-a u` inserts a bare url, delimited by angle brackets. When
177 ;; there is an active region, the text in the region is used as the
178 ;; URL. If the point is at a URL, that url is used. Otherwise,
179 ;; insert angle brackets and position the point in between them
180 ;; for inserting the URL.
182 ;; `C-c C-a f` inserts a footnote marker at the point, inserts a
183 ;; footnote definition below, and positions the point for
184 ;; inserting the footnote text. Note that footnotes are an
185 ;; extension to Markdown and are not supported by all processors.
187 ;; `C-c C-a w` behaves much like the inline link insertion command
188 ;; and inserts a wiki link of the form `[[WikiLink]]`. If there
189 ;; is an active region, use the region as the link text. If the
190 ;; point is at a word, use the word as the link text. If there is
191 ;; no active region and the point is not at word, simply insert
192 ;; link markup. Note that wiki links are an extension to Markdown
193 ;; and are not supported by all processors.
195 ;; * Images: `C-c C-i`
197 ;; `C-c C-i i` inserts markup for an inline image, using the
198 ;; active region or the word at point, if any, as the alt text.
199 ;; `C-c C-i I` behaves similarly and inserts a reference-style
200 ;; image.
202 ;; * Styles: `C-c C-s`
204 ;; `C-c C-s e` inserts markup to make a region or word italic (`e`
205 ;; for `<em>` or emphasis). If there is an active region, make
206 ;; the region italic. If the point is at a non-italic word, make
207 ;; the word italic. If the point is at an italic word or phrase,
208 ;; remove the italic markup. Otherwise, simply insert italic
209 ;; delimiters and place the cursor in between them. Similarly,
210 ;; use `C-c C-s s` for bold (`<strong>`), `C-c C-s c` for
211 ;; inline code (`<code>`), and `C-c C-s k` for inserting `<kbd>`
212 ;; tags.
214 ;; `C-c C-s b` inserts a blockquote using the active region, if any,
215 ;; or starts a new blockquote. `C-c C-s C-b` is a variation which
216 ;; always operates on the region, regardless of whether it is
217 ;; active or not. The appropriate amount of indentation, if any,
218 ;; is calculated automatically given the surrounding context, but
219 ;; may be adjusted later using the region indentation commands.
221 ;; `C-c C-s p` behaves similarly for inserting preformatted code
222 ;; blocks, with `C-c C-s C-p` being the region-only counterpart.
224 ;; * Headings: `C-c C-t`
226 ;; All heading insertion commands use the text in the active
227 ;; region, if any, as the heading text. Otherwise, if the current
228 ;; line is not blank, they use the text on the current line.
229 ;; Finally, the setext commands will prompt for heading text if
230 ;; there is no active region and the current line is blank.
232 ;; `C-c C-t h` inserts a heading with automatically chosen type and
233 ;; level (both determined by the previous heading). `C-c C-t H`
234 ;; behaves similarly, but uses setext (underlined) headings when
235 ;; possible, still calculating the level automatically.
236 ;; In cases where the automatically-determined level is not what
237 ;; you intended, the level can be quickly promoted or demoted
238 ;; (as described below). Alternatively, a `C-u` prefix can be
239 ;; given to insert a heading promoted by one level or a `C-u C-u`
240 ;; prefix can be given to insert a heading demoted by one level.
242 ;; To insert a heading of a specific level and type, use `C-c C-t 1`
243 ;; through `C-c C-t 6` for atx (hash mark) headings and `C-c C-t !` or
244 ;; `C-c C-t @` for setext headings of level one or two, respectively.
245 ;; Note that `!` is `S-1` and `@` is `S-2`.
247 ;; If the point is at a heading, these commands will replace the
248 ;; existing markup in order to update the level and/or type of the
249 ;; heading. To remove the markup of the heading at the point,
250 ;; press `C-c C-k` to kill the heading and press `C-y` to yank the
251 ;; heading text back into the buffer.
253 ;; * Horizontal Rules: `C-c -`
255 ;; `C-c -` inserts a horizontal rule. By default, insert the
256 ;; first string in the list `markdown-hr-strings' (the most
257 ;; prominent rule). With a `C-u` prefix, insert the last string.
258 ;; With a numeric prefix `N`, insert the string in position `N`
259 ;; (counting from 1).
261 ;; * Markdown and Maintenance Commands: `C-c C-c`
263 ;; *Compile:* `C-c C-c m` will run Markdown on the current buffer
264 ;; and show the output in another buffer. *Preview*: `C-c C-c p`
265 ;; runs Markdown on the current buffer and previews, stores the
266 ;; output in a temporary file, and displays the file in a browser.
267 ;; *Export:* `C-c C-c e` will run Markdown on the current buffer
268 ;; and save the result in the file `basename.html`, where
269 ;; `basename` is the name of the Markdown file with the extension
270 ;; removed. *Export and View:* press `C-c C-c v` to export the
271 ;; file and view it in a browser. *Open:* `C-c C-c o` will open
272 ;; the Markdown source file directly using `markdown-open-command'.
273 ;; *Live Export*: Press `C-c C-c l` to turn on
274 ;; `markdown-live-preview-mode' to view the exported output
275 ;; side-by-side with the source Markdown. **For all export commands,
276 ;; the output file will be overwritten without notice.**
277 ;; `markdown-live-preview-window-function' can be customized to open
278 ;; in a browser other than `eww'.
280 ;; To summarize:
282 ;; - `C-c C-c m`: `markdown-command' > `*markdown-output*` buffer.
283 ;; - `C-c C-c p`: `markdown-command' > temporary file > browser.
284 ;; - `C-c C-c e`: `markdown-command' > `basename.html`.
285 ;; - `C-c C-c v`: `markdown-command' > `basename.html` > browser.
286 ;; - `C-c C-c w`: `markdown-command' > kill ring.
287 ;; - `C-c C-c o`: `markdown-open-command'.
288 ;; - `C-c C-c l`: `markdown-live-preview-mode' > `*eww*` buffer.
290 ;; `C-c C-c c` will check for undefined references. If there are
291 ;; any, a small buffer will open with a list of undefined
292 ;; references and the line numbers on which they appear. In Emacs
293 ;; 22 and greater, selecting a reference from this list and
294 ;; pressing `RET` will insert an empty reference definition at the
295 ;; end of the buffer. Similarly, selecting the line number will
296 ;; jump to the corresponding line.
298 ;; `C-c C-c n` renumbers any ordered lists in the buffer that are
299 ;; out of sequence.
301 ;; `C-c C-c ]` completes all headings and normalizes all horizontal
302 ;; rules in the buffer.
304 ;; * Following Links: `C-c C-o`
306 ;; Press `C-c C-o` when the point is on an inline or reference
307 ;; link to open the URL in a browser. When the point is at a
308 ;; wiki link, open it in another buffer (in the current window,
309 ;; or in the other window with the `C-u` prefix). Use `M-p` and
310 ;; `M-n` to quickly jump to the previous or next link of any type.
312 ;; * Jumping: `C-c C-l`
314 ;; Use `C-c C-l` to jump from the object at point to its counterpart
315 ;; elsewhere in the text, when possible. Jumps between reference
316 ;; links and definitions; between footnote markers and footnote
317 ;; text. If more than one link uses the same reference name, a
318 ;; new buffer will be created containing clickable buttons for jumping
319 ;; to each link. You may press `TAB` or `S-TAB` to jump between
320 ;; buttons in this window.
322 ;; * Promotion and Demotion: `C-c C--` and `C-c C-=`
324 ;; Headings, horizontal rules, and list items can be promoted and
325 ;; demoted, as well as bold and italic text. For headings,
326 ;; "promotion" means *decreasing* the level (i.e., moving from
327 ;; `<h2>` to `<h1>`) while "demotion" means *increasing* the
328 ;; level. For horizontal rules, promotion and demotion means
329 ;; moving backward or forward through the list of rule strings in
330 ;; `markdown-hr-strings'. For bold and italic text, promotion and
331 ;; demotion means changing the markup from underscores to asterisks.
332 ;; Press `C-c C--` or `M-LEFT` to promote the element at the point
333 ;; if possible.
335 ;; To remember these commands, note that `-` is for decreasing the
336 ;; level (promoting), and `=` (on the same key as `+`) is for
337 ;; increasing the level (demoting). Similarly, the left and right
338 ;; arrow keys indicate the direction that the atx heading markup
339 ;; is moving in when promoting or demoting.
341 ;; * Completion: `C-c C-]`
343 ;; Complete markup is in normalized form, which means, for
344 ;; example, that the underline portion of a setext header is the
345 ;; same length as the heading text, or that the number of leading
346 ;; and trailing hash marks of an atx header are equal and that
347 ;; there is no extra whitespace in the header text. `C-c C-]`
348 ;; completes the markup at the point, if it is determined to be
349 ;; incomplete.
351 ;; * Editing Lists: `M-RET`, `M-UP`, `M-DOWN`, `M-LEFT`, and `M-RIGHT`
353 ;; New list items can be inserted with `M-RET` or `C-c C-j`. This
354 ;; command determines the appropriate marker (one of the possible
355 ;; unordered list markers or the next number in sequence for an
356 ;; ordered list) and indentation level by examining nearby list
357 ;; items. If there is no list before or after the point, start a
358 ;; new list. Prefix this command by `C-u` to decrease the
359 ;; indentation by one level. Prefix this command by `C-u C-u` to
360 ;; increase the indentation by one level.
362 ;; Existing list items can be moved up or down with `M-UP` or
363 ;; `M-DOWN` and indented or exdented with `M-RIGHT` or `M-LEFT`.
365 ;; * Editing Subtrees: `M-S-UP`, `M-S-DOWN`, `M-S-LEFT`, and `M-S-RIGHT`
367 ;; Entire subtrees of ATX headings can be promoted and demoted
368 ;; with `M-S-LEFT` and `M-S-RIGHT`, which mirror the bindings
369 ;; for promotion and demotion of list items. Similarly, subtrees
370 ;; can be moved up and down with `M-S-UP` and `M-S-DOWN`.
372 ;; Please note the following "boundary" behavior for promotion and
373 ;; demotion. Any level-six headings will not be demoted further
374 ;; (i.e., they remain at level six, since Markdown and HTML define
375 ;; only six levels) and any level-one headings will promoted away
376 ;; entirely (i.e., heading markup will be removed, since a
377 ;; level-zero heading is not defined).
379 ;; * Shifting the Region: `C-c <` and `C-c >`
381 ;; Text in the region can be indented or exdented as a group using
382 ;; `C-c >` to indent to the next indentation point (calculated in
383 ;; the current context), and `C-c <` to exdent to the previous
384 ;; indentation point. These keybindings are the same as those for
385 ;; similar commands in `python-mode'.
387 ;; * Killing Elements: `C-c C-k`
389 ;; Press `C-c C-k` to kill the thing at point and add important
390 ;; text, without markup, to the kill ring. Possible things to
391 ;; kill include (roughly in order of precedece): inline code,
392 ;; headings, horizonal rules, links (add link text to kill ring),
393 ;; images (add alt text to kill ring), angle URIs, email
394 ;; addresses, bold, italics, reference definitions (add URI to
395 ;; kill ring), footnote markers and text (kill both marker and
396 ;; text, add text to kill ring), and list items.
398 ;; * Outline Navigation: `C-c C-n`, `C-c C-p`, `C-c C-f`, `C-c C-b`, and `C-c C-u`
400 ;; Navigation between headings is possible using `outline-mode'.
401 ;; Use `C-c C-n` and `C-c C-p` to move between the next and previous
402 ;; visible headings. Similarly, `C-c C-f` and `C-c C-b` move to the
403 ;; next and previous visible headings at the same level as the one
404 ;; at the point. Finally, `C-c C-u` will move up to a lower-level
405 ;; (higher precedence) visible heading.
407 ;; * Movement by Paragraph or Block: `M-{` and `M-}`
409 ;; The definition of a "paragraph" is slightly different in
410 ;; markdown-mode than, say, text-mode, because markdown-mode
411 ;; supports filling for list items and respects hard line breaks,
412 ;; both of which break paragraphs. So, markdown-mode overrides
413 ;; the usual paragraph navigation commands `M-{` and `M-}` so that
414 ;; with a `C-u` prefix, these commands jump to the beginning or
415 ;; end of an entire block of text, respectively, where "blocks"
416 ;; are separated by one or more lines.
418 ;; * Movement by Defun: `C-M-a`, `C-M-e`, and `C-M-h`
420 ;; The usual Emacs commands can be used to move by defuns
421 ;; (top-level major definitions). In markdown-mode, a defun is a
422 ;; section. As usual, `C-M-a` will move the point to the
423 ;; beginning of the current or preceding defun, `C-M-e` will move
424 ;; to the end of the current or following defun, and `C-M-h` will
425 ;; put the region around the entire defun.
427 ;; As noted, many of the commands above behave differently depending
428 ;; on whether Transient Mark mode is enabled or not. When it makes
429 ;; sense, if Transient Mark mode is on and the region is active, the
430 ;; command applies to the text in the region (e.g., `C-c C-s s` makes the
431 ;; region bold). For users who prefer to work outside of Transient
432 ;; Mark mode, since Emacs 22 it can be enabled temporarily by pressing
433 ;; `C-SPC C-SPC`. When this is not the case, many commands then
434 ;; proceed to look work with the word or line at the point.
436 ;; When applicable, commands that specifically act on the region even
437 ;; outside of Transient Mark mode have the same keybinding as their
438 ;; standard counterpart, but the letter is uppercase. For example,
439 ;; `markdown-insert-blockquote' is bound to `C-c C-s b` and only acts on
440 ;; the region in Transient Mark mode while `markdown-blockquote-region'
441 ;; is bound to `C-c C-s B` and always applies to the region (when nonempty).
443 ;; Note that these region-specific functions are useful in many
444 ;; cases where it may not be obvious. For example, yanking text from
445 ;; the kill ring sets the mark at the beginning of the yanked text
446 ;; and moves the point to the end. Therefore, the (inactive) region
447 ;; contains the yanked text. So, `C-y` followed by `C-c C-s C-b` will
448 ;; yank text and turn it into a blockquote.
450 ;; markdown-mode attempts to be flexible in how it handles
451 ;; indentation. When you press `TAB` repeatedly, the point will cycle
452 ;; through several possible indentation levels corresponding to things
453 ;; you might have in mind when you press `RET` at the end of a line or
454 ;; `TAB`. For example, you may want to start a new list item,
455 ;; continue a list item with hanging indentation, indent for a nested
456 ;; pre block, and so on. Exdention is handled similarly when backspace
457 ;; is pressed at the beginning of the non-whitespace portion of a line.
459 ;; markdown-mode supports outline-minor-mode as well as org-mode-style
460 ;; visibility cycling for atx- or hash-style headings. There are two
461 ;; types of visibility cycling: Pressing `S-TAB` cycles globally between
462 ;; the table of contents view (headings only), outline view (top-level
463 ;; headings only), and the full document view. Pressing `TAB` while the
464 ;; point is at a heading will cycle through levels of visibility for the
465 ;; subtree: completely folded, visible children, and fully visible.
466 ;; Note that mixing hash and underline style headings will give undesired
467 ;; results.
469 ;;; Customization:
471 ;; Although no configuration is *necessary* there are a few things
472 ;; that can be customized. The `M-x customize-mode` command
473 ;; provides an interface to all of the possible customizations:
475 ;; * `markdown-command' - the command used to run Markdown (default:
476 ;; `markdown`). This variable may be customized to pass
477 ;; command-line options to your Markdown processor of choice.
479 ;; * `markdown-command-needs-filename' - set to `t' if
480 ;; `markdown-command' does not accept standard input (default:
481 ;; `nil'). When `nil', `markdown-mode' will pass the Markdown
482 ;; content to `markdown-command' using standard input (`stdin`).
483 ;; When set to `t', `markdown-mode' will pass the name of the file
484 ;; as the final command-line argument to `markdown-command'. Note
485 ;; that in the latter case, you will only be able to run
486 ;; `markdown-command' from buffers which are visiting a file.
488 ;; * `markdown-open-command' - the command used for calling a standalone
489 ;; Markdown previewer which is capable of opening Markdown source files
490 ;; directly (default: `nil'). This command will be called
491 ;; with a single argument, the filename of the current buffer.
492 ;; A representative program is the Mac app [Marked 2][], a
493 ;; live-updating Markdown previewer which can be [called from a
494 ;; simple shell script](http://jblevins.org/log/marked-2-command).
496 ;; * `markdown-hr-strings' - list of strings to use when inserting
497 ;; horizontal rules. Different strings will not be distinguished
498 ;; when converted to HTML--they will all be converted to
499 ;; `<hr/>`--but they may add visual distinction and style to plain
500 ;; text documents. To maintain some notion of promotion and
501 ;; demotion, keep these sorted from largest to smallest.
503 ;; * `markdown-bold-underscore' - set to a non-nil value to use two
504 ;; underscores when inserting bold text instead of two asterisks
505 ;; (default: `nil').
507 ;; * `markdown-italic-underscore' - set to a non-nil value to use
508 ;; underscores when inserting italic text instead of asterisks
509 ;; (default: `nil').
511 ;; * `markdown-asymmetric-header' - set to a non-nil value to use
512 ;; asymmetric header styling, placing header characters only on
513 ;; the left of headers (default: `nil').
515 ;; * `markdown-list-indent-width' - depth of indentation for lists
516 ;; when inserting, promoting, and demoting list items (default: 4).
518 ;; * `markdown-indent-function' - the function to use for automatic
519 ;; indentation (default: `markdown-indent-line').
521 ;; * `markdown-indent-on-enter' - set to a non-nil value to
522 ;; automatically indent new lines when the enter key is pressed
523 ;; (default: `t')
525 ;; * `markdown-wiki-link-alias-first' - set to a non-nil value to
526 ;; treat aliased wiki links like `[[link text|PageName]]`
527 ;; (default: `t'). When set to nil, they will be treated as
528 ;; `[[PageName|link text]]'.
530 ;; * `markdown-uri-types' - a list of protocol schemes (e.g., "http")
531 ;; for URIs that `markdown-mode' should highlight.
533 ;; * `markdown-enable-math' - syntax highlighting for LaTeX
534 ;; fragments (default: `nil'). Set this to `t' to turn on math
535 ;; support by default. Math support can be toggled later using
536 ;; the function `markdown-enable-math'."
538 ;; * `markdown-css-paths' - CSS files to link to in XHTML output
539 ;; (default: `nil`).
541 ;; * `markdown-content-type' - when set to a nonempty string, an
542 ;; `http-equiv` attribute will be included in the XHTML `<head>`
543 ;; block (default: `""`). If needed, the suggested values are
544 ;; `application/xhtml+xml` or `text/html`. See also:
545 ;; `markdown-coding-system'.
547 ;; * `markdown-coding-system' - used for specifying the character
548 ;; set identifier in the `http-equiv` attribute when included
549 ;; (default: `nil'). See `markdown-content-type', which must
550 ;; be set before this variable has any effect. When set to `nil',
551 ;; `buffer-file-coding-system' will be used to automatically
552 ;; determine the coding system string (falling back to
553 ;; `iso-8859-1' when unavailable). Common settings are `utf-8'
554 ;; and `iso-latin-1'.
556 ;; * `markdown-xhtml-header-content' - additional content to include
557 ;; in the XHTML `<head>` block (default: `""`).
559 ;; * `markdown-xhtml-standalone-regexp' - a regular expression which
560 ;; `markdown-mode' uses to determine whether the output of
561 ;; `markdown-command' is a standalone XHTML document or an XHTML
562 ;; fragment (default: `"^\\(<\\?xml\\|<!DOCTYPE\\|<html\\)"`). If
563 ;; this regular expression not matched in the first five lines of
564 ;; output, `markdown-mode' assumes the output is a fragment and
565 ;; adds a header and footer.
567 ;; * `markdown-link-space-sub-char' - a character to replace spaces
568 ;; when mapping wiki links to filenames (default: `"_"`).
569 ;; For example, use an underscore for compatibility with the
570 ;; Python Markdown WikiLinks extension. In `gfm-mode', this is
571 ;; set to `"-"` to conform with GitHub wiki links.
573 ;; * `markdown-reference-location' - where to insert reference
574 ;; definitions (default: `header`). The possible locations are
575 ;; the end of the document (`end`), after the current block
576 ;; (`immediately`), before the next header (`header`).
578 ;; * `markdown-footnote-location' - where to insert footnote text
579 ;; (default: `end`). The set of location options is the same as
580 ;; for `markdown-reference-location'.
582 ;; * `markdown-nested-imenu-heading-index' - Use nested imenu
583 ;; heading instead of a flat index (default: `nil'). A nested
584 ;; index may provide more natural browsing from the menu, but a
585 ;; flat list may allow for faster keyboard navigation via tab
586 ;; completion.
588 ;; * `comment-auto-fill-only-comments' - variable is made
589 ;; buffer-local and set to `nil' by default. In programming
590 ;; language modes, when this variable is non-nil, only comments
591 ;; will be filled by auto-fill-mode. However, comments in
592 ;; Markdown documents are rare and the most users probably intend
593 ;; for the actual content of the document to be filled. Making
594 ;; this variable buffer-local allows `markdown-mode' to override
595 ;; the default behavior induced when the global variable is non-nil.
597 ;; * `markdown-gfm-additional-languages', - additional languages to
598 ;; make available, aside from those predefined in
599 ;; `markdown-gfm-recognized-languages', when inserting GFM code
600 ;; blocks (default: `nil`). Language strings must have be trimmed
601 ;; of whitespace and not contain any curly braces. They may be of
602 ;; arbitrary capitalization, though.
604 ;; * `markdown-gfm-use-electric-backquote' - use
605 ;; `markdown-electric-backquote' for interactive insertion of GFM
606 ;; code blocks when backquote is pressed three times (default: `t`).
608 ;; * `markdown-make-gfm-checkboxes-buttons' - Whether GitHub
609 ;; Flavored Markdown style task lists (checkboxes) should be
610 ;; turned into buttons that can be toggled with mouse-1 or RET. If
611 ;; non-nil (default), then buttons are enabled. This works in
612 ;; `markdown-mode' as well as `gfm-mode'.
614 ;; Additionally, the faces used for syntax highlighting can be modified to
615 ;; your liking by issuing `M-x customize-group RET markdown-faces`
616 ;; or by using the "Markdown Faces" link at the bottom of the mode
617 ;; customization screen.
619 ;; [Marked 2]: https://itunes.apple.com/us/app/marked-2/id890031187?mt=12&uo=4&at=11l5Vs&ct=mm
621 ;;; Extensions:
623 ;; Besides supporting the basic Markdown syntax, markdown-mode also
624 ;; includes syntax highlighting for `[[Wiki Links]]` by default. Wiki
625 ;; links may be followed by pressing `C-c C-o` when the point
626 ;; is at a wiki link. Use `M-p` and `M-n` to quickly jump to the
627 ;; previous and next links (including links of other types).
628 ;; Aliased or piped wiki links of the form `[[link text|PageName]]`
629 ;; are also supported. Since some wikis reverse these components, set
630 ;; `markdown-wiki-link-alias-first' to nil to treat them as
631 ;; `[[PageName|link text]]`. By default, Markdown Mode only searches
632 ;; for target files in the current directory. Sequential parent
633 ;; directory search (as in [Ikiwiki][]) can be enabled by setting
634 ;; `markdown-wiki-link-search-parent-directories' to a non-nil value.
636 ;; [Ikiwiki]: https://ikiwiki.info
638 ;; [SmartyPants][] support is possible by customizing `markdown-command'.
639 ;; If you install `SmartyPants.pl` at, say, `/usr/local/bin/smartypants`,
640 ;; then you can set `markdown-command' to `"markdown | smartypants"`.
641 ;; You can do this either by using `M-x customize-group markdown`
642 ;; or by placing the following in your `.emacs` file:
644 ;; (setq markdown-command "markdown | smartypants")
646 ;; [SmartyPants]: http://daringfireball.net/projects/smartypants/
648 ;; Syntax highlighting for mathematical expressions written
649 ;; in LaTeX (only expressions denoted by `$..$`, `$$..$$`, or `\[..\]`)
650 ;; can be enabled by setting `markdown-enable-math' to a non-nil value,
651 ;; either via customize or by placing `(setq markdown-enable-math t)`
652 ;; in `.emacs`, and then restarting Emacs or calling
653 ;; `markdown-reload-extensions'.
655 ;;; GitHub Flavored Markdown (GFM):
657 ;; A [GitHub Flavored Markdown][GFM] mode, `gfm-mode', is also
658 ;; available. The GitHub implementation differs slightly from
659 ;; standard Markdown in that it supports things like different
660 ;; behavior for underscores inside of words, automatic linking of
661 ;; URLs, strikethrough text, and fenced code blocks with an optional
662 ;; language keyword.
664 ;; The GFM-specific features above apply to `README.md` files, wiki
665 ;; pages, and other Markdown-formatted files in repositories on
666 ;; GitHub. GitHub also enables [additional features][GFM comments] for
667 ;; writing on the site (for issues, pull requests, messages, etc.)
668 ;; that are further extensions of GFM. These features include task
669 ;; lists (checkboxes), newlines corresponding to hard line breaks,
670 ;; auto-linked references to issues and commits, wiki links, and so
671 ;; on. To make matters more confusing, although task lists are not
672 ;; part of [GFM proper][GFM], [since 2014][] they are rendered (in a
673 ;; read-only fashion) in all Markdown documents in repositories on the
674 ;; site. These additional extensions are supported to varying degrees
675 ;; by `markdown-mode' and `gfm-mode' as described below.
677 ;; * **URL autolinking:** Both `markdown-mode' and `gfm-mode' support
678 ;; highlighting of URLs without angle brackets.
680 ;; * **Multiple underscores in words:** You must enable `gfm-mode' to
681 ;; toggle support for underscores inside of words. In this mode
682 ;; variable names such as `a_test_variable` will not trigger
683 ;; emphasis (italics).
685 ;; * **Fenced code blocks:** Code blocks quoted with backticks, with
686 ;; optional programming language keywords, are highlighted in
687 ;; both `markdown-mode' and `gfm-mode'. They can be inserted with
688 ;; `C-c C-s P`. If there is an active region, the text in the
689 ;; region will be placed inside the code block. You will be
690 ;; prompted for the name of the language, but may press enter to
691 ;; continue without naming a language.
693 ;; * **Strikethrough:** Strikethrough text is only supported in
694 ;; `gfm-mode' and can be inserted (and toggled) using `C-c C-s d`.
695 ;; Following the mnemonics for the other style keybindings, the
696 ;; letter `d` coincides with the HTML tag `<del>`.
698 ;; * **Task lists:** GFM task lists will be rendered as checkboxes
699 ;; (Emacs buttons) in both `markdown-mode' and `gfm-mode' when
700 ;; `markdown-make-gfm-checkboxes-buttons' is set to a non-nil value
701 ;; (and it is set to t by default). These checkboxes can be
702 ;; toggled by clicking `mouse-1` or pressing `RET` over the button.
704 ;; * **Wiki links:** Generic wiki links are supported in
705 ;; `markdown-mode', but in `gfm-mode' specifically they will be
706 ;; treated as they are on GitHub: spaces will be replaced by hyphens
707 ;; in filenames and the first letter of the filename will be
708 ;; capitalized. For example, `[[wiki link]]' will map to a file
709 ;; named `Wiki-link` with the same extension as the current file.
711 ;; * **Newlines:** Neither `markdown-mode' nor `gfm-mode' do anything
712 ;; specifically with respect to newline behavior. If you use
713 ;; `gfm-mode' mostly to write text for comments or issues on the
714 ;; GitHub site--where newlines are significant and correspond to
715 ;; hard line breaks--then you may want to enable `visual-line-mode'
716 ;; for line wrapping in buffers. You can do this with a
717 ;; `gfm-mode-hook' as follows:
719 ;; ;; Use visual-line-mode in gfm-mode
720 ;; (defun my-gfm-mode-hook ()
721 ;; (visual-line-mode 1))
722 ;; (add-hook 'gfm-mode-hook 'my-gfm-mode-hook)
724 ;; * **Preview:** GFM-specific preview can be powered by setting
725 ;; `markdown-command' to use [Docter][]. This may also be
726 ;; configured to work with [Marked 2][] for `markdown-open-command'.
728 ;; [GFM]: http://github.github.com/github-flavored-markdown/
729 ;; [GFM comments]: https://help.github.com/articles/writing-on-github/
730 ;; [since 2014]: https://github.com/blog/1825-task-lists-in-all-markdown-documents
731 ;; [Docter]: https://github.com/alampros/Docter
733 ;;; Acknowledgments:
735 ;; markdown-mode has benefited greatly from the efforts of the
736 ;; following people:
738 ;; * Cyril Brulebois <cyril.brulebois@enst-bretagne.fr> for Debian packaging.
739 ;; * Conal Elliott <conal@conal.net> for a font-lock regexp patch.
740 ;; * Edward O'Connor <hober0@gmail.com> for a font-lock regexp fix and
741 ;; GitHub Flavored Markdown mode (`gfm-mode').
742 ;; * Greg Bognar <greg_bognar@hms.harvard.edu> for menus and running
743 ;; `markdown' with an active region.
744 ;; * Daniel Burrows <dburrows@debian.org> for filing Debian bug #456592.
745 ;; * Peter S. Galbraith <psg@debian.org> for maintaining `emacs-goodies-el`.
746 ;; * Dmitry Dzhus <mail@sphinx.net.ru> for undefined reference checking.
747 ;; * Carsten Dominik <carsten@orgmode.org> for `org-mode', from which the
748 ;; visibility cycling functionality was derived, and for a bug fix
749 ;; related to `orgtbl-mode'.
750 ;; * Bryan Kyle <bryan.kyle@gmail.com> for indentation code.
751 ;; * Ben Voui <intrigeri@boum.org> for font-lock face customizations.
752 ;; * Ankit Solanki <ankit.solanki@gmail.com> for `longlines.el`
753 ;; compatibility and custom CSS.
754 ;; * Hilko Bengen <bengen@debian.org> for proper XHTML output.
755 ;; * Jose A. Ortega Ruiz <jao@gnu.org> for Emacs 23 fixes.
756 ;; * Nelson Minar <nelson@santafe.edu> for `html-helper-mode', from which
757 ;; comment matching functions were derived.
758 ;; * Alec Resnick <alec@sproutward.org> for bug reports.
759 ;; * Joost Kremers <joostkremers@fastmail.fm> for footnote-handling
760 ;; functions, bug reports regarding indentation, and
761 ;; fixes for byte-compilation warnings.
762 ;; * Peter Williams <pezra@barelyenough.org> for `fill-paragraph'
763 ;; enhancements.
764 ;; * George Ogata <george.ogata@gmail.com> for fixing several
765 ;; byte-compilation warnings.
766 ;; * Eric Merritt <ericbmerritt@gmail.com> for wiki link features.
767 ;; * Philippe Ivaldi <pivaldi@sfr.fr> for XHTML preview
768 ;; customizations and XHTML export.
769 ;; * Jeremiah Dodds <jeremiah.dodds@gmail.com> for supporting
770 ;; Markdown processors which do not accept input from stdin.
771 ;; * Werner Dittmann <werner.dittmann@t-online.de> for bug reports
772 ;; regarding the `cl` dependency and `auto-fill-mode' and indentation.
773 ;; * Scott Pfister <scott.pfister@gmail.com> for generalizing the space
774 ;; substitution character for mapping wiki links to filenames.
775 ;; * Marcin Kasperski <marcin.kasperski@mekk.waw.pl> for a patch to
776 ;; escape shell commands.
777 ;; * Christopher J. Madsen <cjm@cjmweb.net> for patches to fix a match
778 ;; data bug and to prefer `visual-line-mode' in `gfm-mode'.
779 ;; * Shigeru Fukaya <shigeru.fukaya@gmail.com> for better adherence to
780 ;; Emacs Lisp coding conventions.
781 ;; * Donald Ephraim Curtis <dcurtis@milkbox.net> for fixing the `fill-paragraph'
782 ;; regexp, refactoring the compilation and preview functions,
783 ;; heading font-lock generalizations, list renumbering,
784 ;; and kill ring save.
785 ;; * Kevin Porter <kportertx@gmail.com> for wiki link handling in `gfm-mode'.
786 ;; * Max Penet <max.penet@gmail.com> and Peter Eisentraut <peter_e@gmx.net>
787 ;; for an autoload token for `gfm-mode'.
788 ;; * Ian Yang <me@iany.me> for improving the reference definition regex.
789 ;; * Akinori Musha <knu@idaemons.org> for an imenu index function.
790 ;; * Michael Sperber <sperber@deinprogramm.de> for XEmacs fixes.
791 ;; * Francois Gannaz <francois.gannaz@free.fr> for suggesting charset
792 ;; declaration in XHTML output.
793 ;; * Zhenlei Jia <zhenlei.jia@gmail.com> for smart exdention function.
794 ;; * Matus Goljer <dota.keys@gmail.com> for improved wiki link following
795 ;; and GFM code block insertion.
796 ;; * Peter Jones <pjones@pmade.com> for link following functions.
797 ;; * Bryan Fink <bryan.fink@gmail.com> for a bug report regarding
798 ;; externally modified files.
799 ;; * Vegard Vesterheim <vegard.vesterheim@uninett.no> for a bug fix
800 ;; related to `orgtbl-mode'.
801 ;; * Makoto Motohashi <mkt.motohashi@gmail.com> for before- and after-
802 ;; export hooks, unit test improvements, and updates to support
803 ;; wide characters.
804 ;; * Michael Dwyer <mdwyer@ehtech.in> for `gfm-mode' underscore regexp.
805 ;; * Chris Lott <chris@chrislott.org> for suggesting reference label
806 ;; completion.
807 ;; * Gunnar Franke <Gunnar.Franke@gmx.de> for a completion bug report.
808 ;; * David Glasser <glasser@meteor.com> for a `paragraph-separate' fix.
809 ;; * Daniel Brotsky <dev@brotsky.com> for better auto-fill defaults.
810 ;; * Samuel Freilich <sfreilich@google.com> for improved filling
811 ;; behavior regarding list items, footnotes, and reference
812 ;; definitions, improved killing of footnotes, and numerous other
813 ;; tests and bug fixes.
814 ;; * Antonis Kanouras <antonis@metadosis.gr> for strikethrough support.
815 ;; * Tim Visher <tim.visher@gmail.com> for multiple CSS files and other
816 ;; general improvements.
817 ;; * Matt McClure <matthewlmcclure@gmail.com> for a patch to prevent
818 ;; overwriting source files with .html extensions upon export.
819 ;; * Roger Bolsius <roger.bolsius@gmail.com> for ordered list improvements.
820 ;; * Google's Open Source Programs Office for recognizing the project with
821 ;; a monetary contribution in June 2015.
822 ;; * Howard Melman <hmelman@gmail.com> for supporting GFM checkboxes
823 ;; as buttons.
824 ;; * Danny McClanahan <danieldmcclanahan@gmail.com> for live preview mode,
825 ;; completion of GFM programming language names, and `cl-lib' updates.
826 ;; * Syohei Yoshida <syohex@gmail.com> for better heading detection
827 ;; and movement functions, improved italic font lock, and fixing adaptive
828 ;; filling for hanging list items.
830 ;;; Bugs:
832 ;; markdown-mode is developed and tested primarily for compatibility
833 ;; with GNU Emacs 24.3 and later. If you find any bugs in
834 ;; markdown-mode, please construct a test case or a patch and open a
835 ;; ticket on the [GitHub issue tracker][issues].
837 ;; [issues]: https://github.com/jrblevin/markdown-mode/issues
839 ;;; History:
841 ;; markdown-mode was written and is maintained by Jason Blevins. The
842 ;; first version was released on May 24, 2007.
844 ;; * 2007-05-24: Version 1.1
845 ;; * 2007-05-25: Version 1.2
846 ;; * 2007-06-05: [Version 1.3][]
847 ;; * 2007-06-29: Version 1.4
848 ;; * 2007-10-11: [Version 1.5][]
849 ;; * 2008-06-04: [Version 1.6][]
850 ;; * 2009-10-01: [Version 1.7][]
851 ;; * 2011-08-12: [Version 1.8][]
852 ;; * 2011-08-15: [Version 1.8.1][]
853 ;; * 2013-01-25: [Version 1.9][]
854 ;; * 2013-03-24: [Version 2.0][]
855 ;; * 2016-01-09: [Version 2.1][]
857 ;; [Version 1.3]: http://jblevins.org/projects/markdown-mode/rev-1-3
858 ;; [Version 1.5]: http://jblevins.org/projects/markdown-mode/rev-1-5
859 ;; [Version 1.6]: http://jblevins.org/projects/markdown-mode/rev-1-6
860 ;; [Version 1.7]: http://jblevins.org/projects/markdown-mode/rev-1-7
861 ;; [Version 1.8]: http://jblevins.org/projects/markdown-mode/rev-1-8
862 ;; [Version 1.8.1]: http://jblevins.org/projects/markdown-mode/rev-1-8-1
863 ;; [Version 1.9]: http://jblevins.org/projects/markdown-mode/rev-1-9
864 ;; [Version 2.0]: http://jblevins.org/projects/markdown-mode/rev-2-0
865 ;; [Version 2.1]: http://jblevins.org/projects/markdown-mode/rev-2-1
868 ;;; Code:
870 (require 'easymenu)
871 (require 'outline)
872 (require 'thingatpt)
873 (require 'cl-lib)
875 (declare-function eww-open-file "eww")
878 ;;; Constants =================================================================
880 (defconst markdown-mode-version "2.1"
881 "Markdown mode version number.")
883 (defconst markdown-output-buffer-name "*markdown-output*"
884 "Name of temporary buffer for markdown command output.")
887 ;;; Global Variables ==========================================================
889 (defvar markdown-reference-label-history nil
890 "History of used reference labels.")
892 (defvar markdown-live-preview-mode nil
893 "Sentinel variable for `markdown-live-preview-mode'.")
895 (defvar markdown-gfm-language-history nil
896 "History list of languages used in the current buffer in GFM code blocks.")
899 ;;; Customizable Variables ====================================================
901 (defvar markdown-mode-hook nil
902 "Hook run when entering Markdown mode.")
904 (defvar markdown-before-export-hook nil
905 "Hook run before running Markdown to export XHTML output.
906 The hook may modify the buffer, which will be restored to it's
907 original state after exporting is complete.")
909 (defvar markdown-after-export-hook nil
910 "Hook run after XHTML output has been saved.
911 Any changes to the output buffer made by this hook will be saved.")
913 (defgroup markdown nil
914 "Major mode for editing text files in Markdown format."
915 :prefix "markdown-"
916 :group 'wp
917 :link '(url-link "http://jblevins.org/projects/markdown-mode/"))
919 (defcustom markdown-command "markdown"
920 "Command to run markdown."
921 :group 'markdown
922 :type 'string)
924 (defcustom markdown-command-needs-filename nil
925 "Set to non-nil if `markdown-command' does not accept input from stdin.
926 Instead, it will be passed a filename as the final command line
927 option. As a result, you will only be able to run Markdown from
928 buffers which are visiting a file."
929 :group 'markdown
930 :type 'boolean)
932 (defcustom markdown-open-command nil
933 "Command used for opening Markdown files directly.
934 For example, a standalone Markdown previewer. This command will
935 be called with a single argument: the filename of the current
936 buffer."
937 :group 'markdown
938 :type 'string)
940 (defcustom markdown-hr-strings
941 '("-------------------------------------------------------------------------------"
942 "* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *"
943 "---------------------------------------"
944 "* * * * * * * * * * * * * * * * * * * *"
945 "---------"
946 "* * * * *")
947 "Strings to use when inserting horizontal rules.
948 The first string in the list will be the default when inserting a
949 horizontal rule. Strings should be listed in decreasing order of
950 prominence (as in headings from level one to six) for use with
951 promotion and demotion functions."
952 :group 'markdown
953 :type 'list)
955 (defcustom markdown-bold-underscore nil
956 "Use two underscores when inserting bold text instead of two asterisks."
957 :group 'markdown
958 :type 'boolean)
960 (defcustom markdown-italic-underscore nil
961 "Use underscores when inserting italic text instead of asterisks."
962 :group 'markdown
963 :type 'boolean)
965 (defcustom markdown-asymmetric-header nil
966 "Determines if header style will be asymmetric.
967 Set to non-nil to only have header characters to the left of the title.
968 The default will ensure header characters are placed to the left and right
969 of the title."
970 :group 'markdown
971 :type 'boolean)
973 (defcustom markdown-indent-function 'markdown-indent-line
974 "Function to use to indent."
975 :group 'markdown
976 :type 'function)
978 (defcustom markdown-indent-on-enter t
979 "Automatically indent new lines when enter key is pressed.
980 When this variable is set to t, pressing RET will call
981 `newline-and-indent'. When set to nil, define RET to call
982 `newline' as usual. In the latter case, you can still use
983 auto-indentation by pressing \\[newline-and-indent]."
984 :group 'markdown
985 :type 'boolean)
987 (defcustom markdown-wiki-link-alias-first t
988 "When non-nil, treat aliased wiki links like [[alias text|PageName]].
989 Otherwise, they will be treated as [[PageName|alias text]]."
990 :group 'markdown
991 :type 'boolean
992 :safe 'booleanp)
994 (defcustom markdown-wiki-link-search-parent-directories nil
995 "When non-nil, search for wiki link targets in parent directories.
996 This is the default search behavior of Ikiwiki."
997 :group 'markdown
998 :type 'boolean
999 :safe 'booleanp)
1001 (defcustom markdown-uri-types
1002 '("acap" "cid" "data" "dav" "fax" "file" "ftp" "gopher" "http" "https"
1003 "imap" "ldap" "mailto" "mid" "modem" "news" "nfs" "nntp" "pop" "prospero"
1004 "rtsp" "service" "sip" "tel" "telnet" "tip" "urn" "vemmi" "wais")
1005 "Link types for syntax highlighting of URIs."
1006 :group 'markdown
1007 :type 'list)
1009 (defcustom markdown-enable-math nil
1010 "Syntax highlighting for inline LaTeX and itex expressions.
1011 Set this to a non-nil value to turn on math support by default.
1012 Math support can be toggled later using `markdown-enable-math'
1013 or \\[markdown-enable-math]."
1014 :group 'markdown
1015 :type 'boolean
1016 :safe 'booleanp)
1018 (defcustom markdown-css-paths nil
1019 "URL of CSS file to link to in the output XHTML."
1020 :group 'markdown
1021 :type 'list)
1023 (defcustom markdown-content-type ""
1024 "Content type string for the http-equiv header in XHTML output.
1025 When set to a non-empty string, insert the http-equiv attribute.
1026 Otherwise, this attribute is omitted."
1027 :group 'markdown
1028 :type 'string)
1030 (defcustom markdown-coding-system nil
1031 "Character set string for the http-equiv header in XHTML output.
1032 Defaults to `buffer-file-coding-system' (and falling back to
1033 `iso-8859-1' when not available). Common settings are `utf-8'
1034 and `iso-latin-1'. Use `list-coding-systems' for more choices."
1035 :group 'markdown
1036 :type 'coding-system)
1038 (defcustom markdown-xhtml-header-content ""
1039 "Additional content to include in the XHTML <head> block."
1040 :group 'markdown
1041 :type 'string)
1043 (defcustom markdown-xhtml-standalone-regexp
1044 "^\\(<\\?xml\\|<!DOCTYPE\\|<html\\)"
1045 "Regexp indicating whether `markdown-command' output is standalone XHTML."
1046 :group 'markdown
1047 :type 'regexp)
1049 (defcustom markdown-link-space-sub-char "_"
1050 "Character to use instead of spaces when mapping wiki links to filenames."
1051 :group 'markdown
1052 :type 'string)
1054 (defcustom markdown-reference-location 'header
1055 "Position where new reference definitions are inserted in the document."
1056 :group 'markdown
1057 :type '(choice (const :tag "At the end of the document" end)
1058 (const :tag "Immediately after the current block" immediately)
1059 (const :tag "Before next header" header)))
1061 (defcustom markdown-footnote-location 'end
1062 "Position where new footnotes are inserted in the document."
1063 :group 'markdown
1064 :type '(choice (const :tag "At the end of the document" end)
1065 (const :tag "Immediately after the current block" immediately)
1066 (const :tag "Before next header" header)))
1068 (defcustom markdown-unordered-list-item-prefix " * "
1069 "String inserted before unordered list items."
1070 :group 'markdown
1071 :type 'string)
1073 (defcustom markdown-nested-imenu-heading-index nil
1074 "Use nested or flat imenu heading index.
1075 A nested index may provide more natural browsing from the menu,
1076 but a flat list may allow for faster keyboard navigation via tab
1077 completion."
1078 :group 'markdown
1079 :type 'boolean)
1081 (defcustom markdown-make-gfm-checkboxes-buttons t
1082 "When non-nil, make GFM checkboxes into buttons."
1083 :group 'markdown
1084 :type 'boolean)
1086 (defcustom markdown-live-preview-window-function
1087 'markdown-live-preview-window-eww
1088 "Function to display preview of Markdown output within Emacs. Function must
1089 update the buffer containing the preview and return the buffer."
1090 :group 'markdown
1091 :type 'function)
1093 (defcustom markdown-live-preview-delete-export 'delete-on-destroy
1094 "Delete exported html file when using `markdown-live-preview-export' on every
1095 export by setting to 'delete-on-export, when quitting
1096 `markdown-live-preview-mode' by setting to 'delete-on-destroy, or not at all
1097 when nil."
1098 :group 'markdown
1099 :type 'symbol)
1101 (defcustom markdown-list-indent-width 4
1102 "Depth of indentation for markdown lists. Used in `markdown-demote-list-item'
1103 and `markdown-promote-list-item'."
1104 :group 'markdown
1105 :type 'integer)
1107 (defcustom markdown-gfm-additional-languages nil
1108 "Additional languages to make available when inserting GFM code
1109 blocks. Language strings must have be trimmed of whitespace and not contain any
1110 curly braces. They may be of arbitrary capitalization, though."
1111 :group 'markdown
1112 :type '(repeat (string :validate markdown-validate-language-string)))
1114 (defcustom markdown-gfm-use-electric-backquote t
1115 "Use `markdown-electric-backquote' when backquote is hit three times."
1116 :group 'markdown
1117 :type 'boolean)
1119 (defcustom markdown-gfm-downcase-languages t
1120 "Downcase suggested languages when inserting them to code blocks with
1121 `markdown-electric-backquote'."
1122 :group 'markdown
1123 :type 'boolean)
1126 ;;; Regular Expressions =======================================================
1128 (defconst markdown-regex-comment-start
1129 "<!--"
1130 "Regular expression matches HTML comment opening.")
1132 (defconst markdown-regex-comment-end
1133 "--[ \t]*>"
1134 "Regular expression matches HTML comment closing.")
1136 (defconst markdown-regex-link-inline
1137 "\\(!\\)?\\(\\[\\)\\([^]^][^]]*\\|\\)\\(\\]\\)\\((\\)\\([^)]*?\\)\\(?:\\s-+\\(\"[^\"]*\"\\)\\)?\\()\\)"
1138 "Regular expression for a [text](file) or an image link ![text](file).
1139 Group 1 matches the leading exclamation point (optional).
1140 Group 2 matches the opening square bracket.
1141 Group 3 matches the text inside the square brackets.
1142 Group 4 matches the closing square bracket.
1143 Group 5 matches the opening parenthesis.
1144 Group 6 matches the URL.
1145 Group 7 matches the title (optional).
1146 Group 8 matches the closing parenthesis.")
1148 (defconst markdown-regex-link-reference
1149 "\\(!\\)?\\(\\[\\)\\([^]^][^]]*\\|\\)\\(\\]\\)[ ]?\\(\\[\\)\\([^]]*?\\)\\(\\]\\)"
1150 "Regular expression for a reference link [text][id].
1151 Group 1 matches the leading exclamation point (optional).
1152 Group 2 matches the opening square bracket for the link text.
1153 Group 3 matches the text inside the square brackets.
1154 Group 4 matches the closing square bracket for the link text.
1155 Group 5 matches the opening square bracket for the reference label.
1156 Group 6 matches the reference label.
1157 Group 7 matches the closing square bracket for the reference label.")
1159 (defconst markdown-regex-reference-definition
1160 "^ \\{0,3\\}\\(\\[\\)\\([^]\n]+?\\)\\(\\]\\)\\(:\\)\\s *\\(.*?\\)\\s *\\( \"[^\"]*\"$\\|$\\)"
1161 "Regular expression for a reference definition.
1162 Group 1 matches the opening square bracket.
1163 Group 2 matches the reference label.
1164 Group 3 matches the closing square bracket.
1165 Group 4 matches the colon.
1166 Group 5 matches the URL.
1167 Group 6 matches the title attribute (optional).")
1169 (defconst markdown-regex-footnote
1170 "\\(\\[\\^\\)\\(.+?\\)\\(\\]\\)"
1171 "Regular expression for a footnote marker [^fn].
1172 Group 1 matches the opening square bracket and carat.
1173 Group 2 matches only the label, without the surrounding markup.
1174 Group 3 matches the closing square bracket.")
1176 (defconst markdown-regex-header
1177 "^\\(?:\\(.+\\)\n\\(=+\\)\\|\\(.+\\)\n\\(-+\\)\\|\\(#+\\)\\s-*\\(.*?\\)\\s-*?\\(#*\\)\\)$"
1178 "Regexp identifying Markdown headings.
1179 Group 1 matches the text of a level-1 setext heading.
1180 Group 2 matches the underline of a level-1 setext heading.
1181 Group 3 matches the text of a level-1 setext heading.
1182 Group 4 matches the underline of a level-1 setext heading.
1183 Group 5 matches the opening hash marks of an atx heading.
1184 Group 6 matches the text, without surrounding whitespace, of an atx heading.
1185 Group 7 matches the closing hash marks of an atx heading.")
1187 (defconst markdown-regex-header-1-atx
1188 "^\\(#\\)[ \t]*\\([^\\.].*?\\)[ \t]*\\(#*\\)$"
1189 "Regular expression for level 1 atx-style (hash mark) headers.")
1191 (defconst markdown-regex-header-2-atx
1192 "^\\(##\\)[ \t]*\\(.+?\\)[ \t]*\\(#*\\)$"
1193 "Regular expression for level 2 atx-style (hash mark) headers.")
1195 (defconst markdown-regex-header-3-atx
1196 "^\\(###\\)[ \t]*\\(.+?\\)[ \t]*\\(#*\\)$"
1197 "Regular expression for level 3 atx-style (hash mark) headers.")
1199 (defconst markdown-regex-header-4-atx
1200 "^\\(####\\)[ \t]*\\(.+?\\)[ \t]*\\(#*\\)$"
1201 "Regular expression for level 4 atx-style (hash mark) headers.")
1203 (defconst markdown-regex-header-5-atx
1204 "^\\(#####\\)[ \t]*\\(.+?\\)[ \t]*\\(#*\\)$"
1205 "Regular expression for level 5 atx-style (hash mark) headers.")
1207 (defconst markdown-regex-header-6-atx
1208 "^\\(######\\)[ \t]*\\(.+?\\)[ \t]*\\(#*\\)$"
1209 "Regular expression for level 6 atx-style (hash mark) headers.")
1211 (defconst markdown-regex-header-1-setext
1212 "^\\(.*\\)\n\\(=+\\)$"
1213 "Regular expression for level 1 setext-style (underline) headers.")
1215 (defconst markdown-regex-header-2-setext
1216 "^\\(.*\\)\n\\(-+\\)$"
1217 "Regular expression for level 2 setext-style (underline) headers.")
1219 (defconst markdown-regex-header-setext
1220 "^\\(.+\\)\n\\(\\(?:=\\|-\\)+\\)$"
1221 "Regular expression for generic setext-style (underline) headers.")
1223 (defconst markdown-regex-header-atx
1224 "^\\(#+\\)[ \t]*\\(.*?\\)[ \t]*\\(#*\\)$"
1225 "Regular expression for generic atx-style (hash mark) headers.")
1227 (defconst markdown-regex-hr
1228 "^\\(\\*[ ]?\\*[ ]?\\*[ ]?[\\* ]*\\|-[ ]?-[ ]?-[--- ]*\\)$"
1229 "Regular expression for matching Markdown horizontal rules.")
1231 (defconst markdown-regex-code
1232 "\\(?:\\`\\|[^\\]\\)\\(\\(`+\\)\\(\\(?:.\\|\n[^\n]\\)*?[^`]\\)\\(\\2\\)\\)\\(?:[^`]\\|\\'\\)"
1233 "Regular expression for matching inline code fragments.
1235 Group 1 matches the entire code fragment including the backticks.
1236 Group 2 matches the opening backticks.
1237 Group 3 matches the code fragment itself, without backticks.
1238 Group 4 matches the closing backticks.
1240 The leading, unnumbered group ensures that the leading backquote
1241 character is not escaped.
1242 The last group, also unnumbered, requires that the character
1243 following the code fragment is not a backquote.
1244 Note that \\(?:.\\|\n[^\n]\\) matches any character, including newlines,
1245 but not two newlines in a row.")
1247 (defconst markdown-regex-kbd
1248 "\\(<kbd>\\)\\(\\(?:.\\|\n[^\n]\\)*?\\)\\(</kbd>\\)"
1249 "Regular expression for matching <kbd> tags.
1250 Groups 1 and 3 match the opening and closing tags.
1251 Group 2 matches the key sequence.")
1253 (defconst markdown-regex-gfm-code-block-open
1254 "^\\s *\\(```\\)[ ]?\\([^[:space:]]+[[:space:]]*\\|{[^}]*}\\)?$"
1255 "Regular expression matching opening of GFM code blocks.
1256 Group 1 matches the opening three backticks.
1257 Group 2 matches the language identifier (optional).
1258 Group 3 matches the closing three backticks.")
1260 (defconst markdown-regex-gfm-code-block-close
1261 "^\\s *\\(```\\)\\s *$"
1262 "Regular expression matching closing of GFM code blocks.
1263 Group 1 matches the closing three backticks.")
1265 (defconst markdown-regex-pre
1266 "^\\( \\|\t\\).*$"
1267 "Regular expression for matching preformatted text sections.")
1269 (defconst markdown-regex-list
1270 "^\\([ \t]*\\)\\([0-9#]+\\.\\|[\\*\\+-]\\)\\([ \t]+\\)"
1271 "Regular expression for matching list items.")
1273 (defconst markdown-regex-bold
1274 "\\(^\\|[^\\]\\)\\(\\([*_]\\{2\\}\\)\\([^ \n\t\\]\\|[^ \n\t]\\(?:.\\|\n[^\n]\\)*?[^\\ ]\\)\\(\\3\\)\\)"
1275 "Regular expression for matching bold text.
1276 Group 1 matches the character before the opening asterisk or
1277 underscore, if any, ensuring that it is not a backslash escape.
1278 Group 2 matches the entire expression, including delimiters.
1279 Groups 3 and 5 matches the opening and closing delimiters.
1280 Group 4 matches the text inside the delimiters.")
1282 (defconst markdown-regex-italic
1283 "\\(?:^\\|[^\\]\\)\\(\\([*_]\\)\\([^ \n\t\\]\\|[^ \n\t]\\(?:.\\|\n[^\n]\\)*?[^\\ ]\\)\\(\\2\\)\\)"
1284 "Regular expression for matching italic text.
1285 The leading unnumbered matches the character before the opening
1286 asterisk or underscore, if any, ensuring that it is not a
1287 backslash escape.
1288 Group 1 matches the entire expression, including delimiters.
1289 Groups 2 and 4 matches the opening and closing delimiters.
1290 Group 3 matches the text inside the delimiters.")
1292 (defconst markdown-regex-strike-through
1293 "\\(^\\|[^\\]\\)\\(\\(~~\\)\\([^ \n\t\\]\\|[^ \n\t]\\(?:.\\|\n[^\n]\\)*?[^\\ ]\\)\\(~~\\)\\)"
1294 "Regular expression for matching strike-through text.
1295 Group 1 matches the character before the opening tilde, if any,
1296 ensuring that it is not a backslash escape.
1297 Group 2 matches the entire expression, including delimiters.
1298 Groups 3 and 5 matches the opening and closing delimiters.
1299 Group 4 matches the text inside the delimiters.")
1301 (defconst markdown-regex-gfm-italic
1302 "\\(?:^\\|\\s-\\)\\(\\([*_]\\)\\([^ \\]\\2\\|[^ ]\\(?:.\\|\n[^\n]\\)*?[^\\ ]\\)\\(\\2\\)\\)"
1303 "Regular expression for matching italic text in GitHub Flavored Markdown.
1304 Underscores in words are not treated as special.
1305 Group 1 matches the entire expression, including delimiters.
1306 Groups 2 and 4 matches the opening and closing delimiters.
1307 Group 3 matches the text inside the delimiters.")
1309 (defconst markdown-regex-blockquote
1310 "^[ \t]*\\(>\\)\\(.*\\)$"
1311 "Regular expression for matching blockquote lines.
1312 Group 1 matches the leading angle bracket.
1313 Group 2 matches the text.")
1315 (defconst markdown-regex-line-break
1316 "[^ \n\t][ \t]*\\( \\)$"
1317 "Regular expression for matching line breaks.")
1319 (defconst markdown-regex-wiki-link
1320 "\\(?:^\\|[^\\]\\)\\(\\(\\[\\[\\)\\([^]|]+\\)\\(?:\\(|\\)\\([^]]+\\)\\)?\\(\\]\\]\\)\\)"
1321 "Regular expression for matching wiki links.
1322 This matches typical bracketed [[WikiLinks]] as well as 'aliased'
1323 wiki links of the form [[PageName|link text]].
1324 The meanings of the first and second components depend
1325 on the value of `markdown-wiki-link-alias-first'.
1327 Group 1 matches the entire link.
1328 Group 2 matches the opening square brackets.
1329 Group 3 matches the first component of the wiki link.
1330 Group 4 matches the pipe separator, when present.
1331 Group 5 matches the second component of the wiki link, when present.
1332 Group 6 matches the closing square brackets.")
1334 (defconst markdown-regex-uri
1335 (concat (regexp-opt markdown-uri-types) ":[^]\t\n\r<>,;() ]+")
1336 "Regular expression for matching inline URIs.")
1338 (defconst markdown-regex-angle-uri
1339 (concat "\\(<\\)\\(" (regexp-opt markdown-uri-types) ":[^]\t\n\r<>,;()]+\\)\\(>\\)")
1340 "Regular expression for matching inline URIs in angle brackets.")
1342 (defconst markdown-regex-email
1343 "<\\(\\(\\sw\\|\\s_\\|\\s.\\)+@\\(\\sw\\|\\s_\\|\\s.\\)+\\)>"
1344 "Regular expression for matching inline email addresses.")
1346 (defconst markdown-regex-link-generic
1347 (concat "\\(?:" markdown-regex-wiki-link
1348 "\\|" markdown-regex-link-inline
1349 "\\|" markdown-regex-link-reference
1350 "\\|" markdown-regex-angle-uri "\\)")
1351 "Regular expression for matching any recognized link.")
1353 (defconst markdown-regex-gfm-checkbox
1354 " \\(\\[[ xX]\\]\\) "
1355 "Regular expression for matching GFM checkboxes.
1356 Group 1 matches the text to become a button.")
1358 (defconst markdown-regex-block-separator
1359 "\\(\\`\\|\\(\n[ \t]*\n\\)[^\n \t]\\)"
1360 "Regular expression for matching block boundaries.")
1362 (defconst markdown-regex-math-inline-single
1363 "\\(?:^\\|[^\\]\\)\\(\\$\\)\\(\\(?:[^\\$]\\|\\\\.\\)*\\)\\(\\$\\)"
1364 "Regular expression for itex $..$ math mode expressions.
1365 Groups 1 and 3 match the opening and closing dollar signs.
1366 Group 3 matches the mathematical expression contained within.")
1368 (defconst markdown-regex-math-inline-double
1369 "\\(?:^\\|[^\\]\\)\\(\\$\\$\\)\\(\\(?:[^\\$]\\|\\\\.\\)*\\)\\(\\$\\$\\)"
1370 "Regular expression for itex $$..$$ math mode expressions.
1371 Groups 1 and 3 match opening and closing dollar signs.
1372 Group 3 matches the mathematical expression contained within.")
1374 (defconst markdown-regex-math-display
1375 "^\\(\\\\\\[\\)\\(\\(?:.\\|\n\\)*\\)?\\(\\\\\\]\\)$"
1376 "Regular expression for itex \[..\] display mode expressions.
1377 Groups 1 and 3 matche the opening and closing delimiters.
1378 Group 2 matches the mathematical expression contained within.")
1380 (defconst markdown-regex-multimarkdown-metadata
1381 "^\\([[:alpha:]][[:alpha:] _-]*?\\)\\(:[ \t]*\\)\\(.*\\)$"
1382 "Regular expression for matching MultiMarkdown metadata.")
1384 (defconst markdown-regex-pandoc-metadata
1385 "^\\(%\\)\\([ \t]*\\)\\(.*\\)$"
1386 "Regular expression for matching Pandoc metadata.")
1389 ;;; Syntax ====================================================================
1391 (defun markdown-syntax-propertize-extend-region (start end)
1392 "Extend START to END region to include an entire block of text.
1393 This helps improve syntax analysis for block constructs.
1394 Returns a cons (NEW-START . NEW-END) or nil if no adjustment should be made.
1395 Function is called repeatedly until it returns nil. For details, see
1396 `syntax-propertize-extend-region-functions'."
1397 (save-excursion
1398 (let* ((new-start (progn (goto-char start)
1399 (if (re-search-backward "\n\n" nil t)
1400 (match-end 0) (point-min))))
1401 (new-end (progn (goto-char end)
1402 (if (re-search-forward "\n\n" nil t)
1403 (match-beginning 0) (point-max))))
1404 (code-match (markdown-code-block-at-pos new-start))
1405 (new-start (or (and code-match (cl-first code-match)) new-start))
1406 (code-match (markdown-code-block-at-pos end))
1407 (new-end (or (and code-match (cl-second code-match)) new-end)))
1408 (unless (and (eq new-start start) (eq new-end end))
1409 (cons new-start new-end)))))
1411 (defun markdown-syntax-propertize-pre-blocks (start end)
1412 "Match preformatted text blocks from START to END."
1413 (save-excursion
1414 (goto-char start)
1415 (let ((levels (markdown-calculate-list-levels))
1416 indent pre-regexp close-regexp open close stop)
1417 (while (and (< (point) end) (not close))
1418 ;; Search for a region with sufficient indentation
1419 (if (null levels)
1420 (setq indent 1)
1421 (setq indent (1+ (length levels))))
1422 (setq pre-regexp (format "^\\( \\|\t\\)\\{%d\\}" indent))
1423 (setq close-regexp (format "^\\( \\|\t\\)\\{0,%d\\}\\([^ \t]\\)" (1- indent)))
1425 (cond
1426 ;; If not at the beginning of a line, move forward
1427 ((not (bolp)) (forward-line))
1428 ;; Move past blank lines
1429 ((markdown-cur-line-blank-p) (forward-line))
1430 ;; At headers and horizontal rules, reset levels
1431 ((markdown-new-baseline-p) (forward-line) (setq levels nil))
1432 ;; If the current line has sufficient indentation, mark out pre block
1433 ;; The opening should be preceded by a blank line.
1434 ((and (looking-at pre-regexp)
1435 (markdown-prev-line-blank-p))
1436 (setq open (match-beginning 0))
1437 (while (and (or (looking-at pre-regexp) (markdown-cur-line-blank-p))
1438 (not (eobp)))
1439 (forward-line))
1440 (skip-syntax-backward "-")
1441 (setq close (point)))
1442 ;; If current line has a list marker, update levels, move to end of block
1443 ((looking-at markdown-regex-list)
1444 (setq levels (markdown-update-list-levels
1445 (match-string 2) (markdown-cur-line-indent) levels))
1446 (markdown-end-of-block-element))
1447 ;; If this is the end of the indentation level, adjust levels accordingly.
1448 ;; Only match end of indentation level if levels is not the empty list.
1449 ((and (car levels) (looking-at close-regexp))
1450 (setq levels (markdown-update-list-levels
1451 nil (markdown-cur-line-indent) levels))
1452 (markdown-end-of-block-element))
1453 (t (markdown-end-of-block-element))))
1455 (when (and open close)
1456 ;; Set text property data
1457 (put-text-property open close 'markdown-pre (list open close))
1458 ;; Recursively search again
1459 (markdown-syntax-propertize-pre-blocks (point) end)))))
1461 (defun markdown-syntax-propertize-fenced-code-blocks (start end)
1462 "Match tilde-fenced code text blocks from START to END."
1463 (save-excursion
1464 (goto-char start)
1465 (while (re-search-forward "^\\([~]\\{3,\\}\\)" end t)
1466 (let ((beg (match-beginning 1)))
1467 (when (re-search-forward
1468 (concat "^" (match-string 1) "~*") end t)
1469 (put-text-property beg (match-end 0) 'markdown-fenced-code
1470 (list beg (point))))))))
1472 (defun markdown-syntax-propertize-gfm-code-blocks (start end)
1473 "Match GFM code blocks from START to END."
1474 (save-excursion
1475 (goto-char start)
1476 (while (re-search-forward markdown-regex-gfm-code-block-open end t)
1477 (let ((open (list (match-beginning 1) (match-end 1)))
1478 (lang (list (match-beginning 2) (match-end 2))))
1479 (forward-line)
1480 (let ((body (point)))
1481 (when (re-search-forward
1482 markdown-regex-gfm-code-block-close end t)
1483 (let ((close (list (match-beginning 1) (match-end 1)))
1484 (all (list (car open) (match-end 1))))
1485 (setq body (list body (1- (match-beginning 0))))
1486 (put-text-property (car open) (match-end 1) 'markdown-gfm-code
1487 (append all open lang body close)))))))))
1489 (defun markdown-syntax-propertize-blockquotes (start end)
1490 "Match blockquotes from START to END."
1491 (save-excursion
1492 (goto-char start)
1493 (while (and (re-search-forward markdown-regex-blockquote end t)
1494 (not (markdown-code-block-at-pos (match-beginning 0))))
1495 (put-text-property (match-beginning 0) (match-end 0)
1496 'markdown-blockquote
1497 (match-data t)))))
1499 (defun markdown-syntax-propertize-headings-generic (symbol regex start end)
1500 "Match headings of type SYMBOL with REGEX from START to END."
1501 (save-excursion
1502 (goto-char start)
1503 (while (re-search-forward regex end t)
1504 (unless (or (markdown-code-block-at-pos (match-beginning 0))
1505 (get-text-property (match-beginning 0) 'markdown-heading))
1506 (put-text-property (match-beginning 0) (match-end 0)
1507 'markdown-heading t)
1508 (put-text-property (match-beginning 0) (match-end 0)
1509 symbol (match-data t))))))
1511 (defun markdown-syntax-propertize-comments (start end)
1512 "Match HTML comments from the START to END."
1513 (let* ((state (syntax-ppss)) (in-comment (nth 4 state)))
1514 (goto-char start)
1515 (cond
1516 ;; Comment start
1517 ((and (not in-comment)
1518 (re-search-forward markdown-regex-comment-start end t)
1519 (save-match-data (not (markdown-code-at-point-p)))
1520 (save-match-data (not (markdown-code-block-at-point))))
1521 (let ((open-beg (match-beginning 0)))
1522 (put-text-property open-beg (1+ open-beg)
1523 'syntax-table (string-to-syntax "<"))
1524 (markdown-syntax-propertize-comments (1+ open-beg) end)))
1525 ;; Comment end
1526 ((and in-comment
1527 (re-search-forward markdown-regex-comment-end end t))
1528 (put-text-property (1- (match-end 0)) (match-end 0)
1529 'syntax-table (string-to-syntax ">"))
1530 (markdown-syntax-propertize-comments (match-end 0) end))
1531 ;; Nothing found
1532 (t nil))))
1534 (defun markdown-syntax-propertize (start end)
1535 "See `syntax-propertize-function'."
1536 (remove-text-properties start end '(markdown-gfm-code))
1537 (remove-text-properties start end '(markdown-fenced-code))
1538 (remove-text-properties start end '(markdown-pre))
1539 (remove-text-properties start end '(markdown-blockquote))
1540 (remove-text-properties start end '(markdown-heading))
1541 (remove-text-properties start end '(markdown-heading-1-setext))
1542 (remove-text-properties start end '(markdown-heading-2-setext))
1543 (remove-text-properties start end '(markdown-heading-1-atx))
1544 (remove-text-properties start end '(markdown-heading-2-atx))
1545 (remove-text-properties start end '(markdown-heading-3-atx))
1546 (remove-text-properties start end '(markdown-heading-4-atx))
1547 (remove-text-properties start end '(markdown-heading-5-atx))
1548 (remove-text-properties start end '(markdown-heading-6-atx))
1549 (markdown-syntax-propertize-gfm-code-blocks start end)
1550 (markdown-syntax-propertize-fenced-code-blocks start end)
1551 (markdown-syntax-propertize-pre-blocks start end)
1552 (markdown-syntax-propertize-blockquotes start end)
1553 (markdown-syntax-propertize-headings-generic
1554 'markdown-heading-1-setext markdown-regex-header-1-setext start end)
1555 (markdown-syntax-propertize-headings-generic
1556 'markdown-heading-2-setext markdown-regex-header-2-setext start end)
1557 (markdown-syntax-propertize-headings-generic
1558 'markdown-heading-6-atx markdown-regex-header-6-atx start end)
1559 (markdown-syntax-propertize-headings-generic
1560 'markdown-heading-5-atx markdown-regex-header-5-atx start end)
1561 (markdown-syntax-propertize-headings-generic
1562 'markdown-heading-4-atx markdown-regex-header-4-atx start end)
1563 (markdown-syntax-propertize-headings-generic
1564 'markdown-heading-3-atx markdown-regex-header-3-atx start end)
1565 (markdown-syntax-propertize-headings-generic
1566 'markdown-heading-2-atx markdown-regex-header-2-atx start end)
1567 (markdown-syntax-propertize-headings-generic
1568 'markdown-heading-1-atx markdown-regex-header-1-atx start end)
1569 (markdown-syntax-propertize-comments start end))
1572 ;;; Font Lock =================================================================
1574 (require 'font-lock)
1576 (defvar markdown-italic-face 'markdown-italic-face
1577 "Face name to use for italic text.")
1579 (defvar markdown-bold-face 'markdown-bold-face
1580 "Face name to use for bold text.")
1582 (defvar markdown-strike-through-face 'markdown-strike-through-face
1583 "Face name to use for strike-through text.")
1585 (defvar markdown-header-delimiter-face 'markdown-header-delimiter-face
1586 "Face name to use as a base for header delimiters.")
1588 (defvar markdown-header-rule-face 'markdown-header-rule-face
1589 "Face name to use as a base for header rules.")
1591 (defvar markdown-header-face 'markdown-header-face
1592 "Face name to use as a base for headers.")
1594 (defvar markdown-header-face-1 'markdown-header-face-1
1595 "Face name to use for level-1 headers.")
1597 (defvar markdown-header-face-2 'markdown-header-face-2
1598 "Face name to use for level-2 headers.")
1600 (defvar markdown-header-face-3 'markdown-header-face-3
1601 "Face name to use for level-3 headers.")
1603 (defvar markdown-header-face-4 'markdown-header-face-4
1604 "Face name to use for level-4 headers.")
1606 (defvar markdown-header-face-5 'markdown-header-face-5
1607 "Face name to use for level-5 headers.")
1609 (defvar markdown-header-face-6 'markdown-header-face-6
1610 "Face name to use for level-6 headers.")
1612 (defvar markdown-inline-code-face 'markdown-inline-code-face
1613 "Face name to use for inline code.")
1615 (defvar markdown-list-face 'markdown-list-face
1616 "Face name to use for list markers.")
1618 (defvar markdown-blockquote-face 'markdown-blockquote-face
1619 "Face name to use for blockquote.")
1621 (defvar markdown-pre-face 'markdown-pre-face
1622 "Face name to use for preformatted text.")
1624 (defvar markdown-language-keyword-face 'markdown-language-keyword-face
1625 "Face name to use for programming language identifiers.")
1627 (defvar markdown-link-face 'markdown-link-face
1628 "Face name to use for links.")
1630 (defvar markdown-missing-link-face 'markdown-missing-link-face
1631 "Face name to use for links where the linked file does not exist.")
1633 (defvar markdown-reference-face 'markdown-reference-face
1634 "Face name to use for reference.")
1636 (defvar markdown-footnote-face 'markdown-footnote-face
1637 "Face name to use for footnote identifiers.")
1639 (defvar markdown-url-face 'markdown-url-face
1640 "Face name to use for URLs.")
1642 (defvar markdown-link-title-face 'markdown-link-title-face
1643 "Face name to use for reference link titles.")
1645 (defvar markdown-line-break-face 'markdown-line-break-face
1646 "Face name to use for hard line breaks.")
1648 (defvar markdown-comment-face 'markdown-comment-face
1649 "Face name to use for HTML comments.")
1651 (defvar markdown-math-face 'markdown-math-face
1652 "Face name to use for LaTeX expressions.")
1654 (defvar markdown-metadata-key-face 'markdown-metadata-key-face
1655 "Face name to use for metadata keys.")
1657 (defvar markdown-metadata-value-face 'markdown-metadata-value-face
1658 "Face name to use for metadata values.")
1660 (defvar markdown-gfm-checkbox-face 'markdown-gfm-checkbox-face
1661 "Face name to use for GFM checkboxes.")
1663 (defvar markdown-highlight-face 'markdown-highlight-face
1664 "Face name to use for mouse highlighting.")
1666 (defvar markdown-markup-face 'markdown-markup-face
1667 "Face name to use for markup elements.")
1669 (defgroup markdown-faces nil
1670 "Faces used in Markdown Mode"
1671 :group 'markdown
1672 :group 'faces)
1674 (defface markdown-italic-face
1675 '((t (:inherit font-lock-variable-name-face :slant italic :weight normal)))
1676 "Face for italic text."
1677 :group 'markdown-faces)
1679 (defface markdown-bold-face
1680 '((t (:inherit font-lock-variable-name-face :weight bold :slant normal)))
1681 "Face for bold text."
1682 :group 'markdown-faces)
1684 (defface markdown-strike-through-face
1685 '((t (:inherit font-lock-variable-name-face :strike-through t)))
1686 "Face for strike-through text."
1687 :group 'markdown-faces)
1689 (defface markdown-markup-face
1690 '((t (:inherit shadow :slant normal :weight normal)))
1691 "Face for markup elements."
1692 :group 'markdown-faces)
1694 (defface markdown-header-rule-face
1695 '((t (:inherit markdown-markup-face)))
1696 "Base face for headers rules."
1697 :group 'markdown-faces)
1699 (defface markdown-header-delimiter-face
1700 '((t (:inherit markdown-markup-face)))
1701 "Base face for headers hash delimiter."
1702 :group 'markdown-faces)
1704 (defface markdown-header-face
1705 '((t (:inherit font-lock-function-name-face :weight bold)))
1706 "Base face for headers."
1707 :group 'markdown-faces)
1709 (defface markdown-header-face-1
1710 '((t (:inherit markdown-header-face)))
1711 "Face for level-1 headers."
1712 :group 'markdown-faces)
1714 (defface markdown-header-face-2
1715 '((t (:inherit markdown-header-face)))
1716 "Face for level-2 headers."
1717 :group 'markdown-faces)
1719 (defface markdown-header-face-3
1720 '((t (:inherit markdown-header-face)))
1721 "Face for level-3 headers."
1722 :group 'markdown-faces)
1724 (defface markdown-header-face-4
1725 '((t (:inherit markdown-header-face)))
1726 "Face for level-4 headers."
1727 :group 'markdown-faces)
1729 (defface markdown-header-face-5
1730 '((t (:inherit markdown-header-face)))
1731 "Face for level-5 headers."
1732 :group 'markdown-faces)
1734 (defface markdown-header-face-6
1735 '((t (:inherit markdown-header-face)))
1736 "Face for level-6 headers."
1737 :group 'markdown-faces)
1739 (defface markdown-inline-code-face
1740 '((t (:inherit font-lock-constant-face)))
1741 "Face for inline code."
1742 :group 'markdown-faces)
1744 (defface markdown-list-face
1745 '((t (:inherit markdown-markup-face)))
1746 "Face for list item markers."
1747 :group 'markdown-faces)
1749 (defface markdown-blockquote-face
1750 '((t (:inherit font-lock-doc-face)))
1751 "Face for blockquote sections."
1752 :group 'markdown-faces)
1754 (defface markdown-pre-face
1755 '((t (:inherit font-lock-constant-face)))
1756 "Face for preformatted text."
1757 :group 'markdown-faces)
1759 (defface markdown-language-keyword-face
1760 '((t (:inherit font-lock-type-face)))
1761 "Face for programming language identifiers."
1762 :group 'markdown-faces)
1764 (defface markdown-link-face
1765 '((t (:inherit font-lock-keyword-face)))
1766 "Face for links."
1767 :group 'markdown-faces)
1769 (defface markdown-missing-link-face
1770 '((t (:inherit font-lock-warning-face)))
1771 "Face for missing links."
1772 :group 'markdown-faces)
1774 (defface markdown-reference-face
1775 '((t (:inherit markdown-markup-face)))
1776 "Face for link references."
1777 :group 'markdown-faces)
1779 (defface markdown-footnote-face
1780 '((t (:inherit markdown-markup-face)))
1781 "Face for footnote markers."
1782 :group 'markdown-faces)
1784 (defface markdown-url-face
1785 '((t (:inherit font-lock-string-face)))
1786 "Face for URLs."
1787 :group 'markdown-faces)
1789 (defface markdown-link-title-face
1790 '((t (:inherit font-lock-comment-face)))
1791 "Face for reference link titles."
1792 :group 'markdown-faces)
1794 (defface markdown-line-break-face
1795 '((t (:inherit font-lock-constant-face :underline t)))
1796 "Face for hard line breaks."
1797 :group 'markdown-faces)
1799 (defface markdown-comment-face
1800 '((t (:inherit font-lock-comment-face)))
1801 "Face for HTML comments."
1802 :group 'markdown-faces)
1804 (defface markdown-math-face
1805 '((t (:inherit font-lock-string-face)))
1806 "Face for LaTeX expressions."
1807 :group 'markdown-faces)
1809 (defface markdown-metadata-key-face
1810 '((t (:inherit font-lock-variable-name-face)))
1811 "Face for metadata keys."
1812 :group 'markdown-faces)
1814 (defface markdown-metadata-value-face
1815 '((t (:inherit font-lock-string-face)))
1816 "Face for metadata values."
1817 :group 'markdown-faces)
1819 (defface markdown-gfm-checkbox-face
1820 '((t (:inherit font-lock-builtin-face)))
1821 "Face for GFM checkboxes."
1822 :group 'markdown-faces)
1824 (defface markdown-highlight-face
1825 '((t (:inherit highlight)))
1826 "Face for mouse highlighting."
1827 :group 'markdown-faces)
1829 (defun markdown-syntactic-face (state)
1830 "Returns a font-lock face for characters with given STATE.
1831 See `font-lock-syntactic-face-function' for details."
1832 (let ((in-comment (nth 4 state)))
1833 (cond
1834 (in-comment 'markdown-comment-face)
1835 (t nil))))
1837 (defvar markdown-mode-font-lock-keywords-basic
1838 (list
1839 (cons 'markdown-match-gfm-code-blocks '((1 markdown-markup-face)
1840 (2 markdown-language-keyword-face nil t)
1841 (3 markdown-pre-face)
1842 (4 markdown-markup-face)))
1843 (cons 'markdown-match-fenced-code-blocks '((0 markdown-pre-face)))
1844 (cons 'markdown-match-pre-blocks '((0 markdown-pre-face)))
1845 (cons 'markdown-match-blockquotes '((1 markdown-markup-face)
1846 (2 markdown-blockquote-face)))
1847 (cons 'markdown-match-heading-1-setext '((1 markdown-header-face-1)
1848 (2 markdown-header-rule-face)))
1849 (cons 'markdown-match-heading-2-setext '((1 markdown-header-face-2)
1850 (2 markdown-header-rule-face)))
1851 (cons 'markdown-match-heading-6-atx '((1 markdown-header-delimiter-face)
1852 (2 markdown-header-face-6)
1853 (3 markdown-header-delimiter-face)))
1854 (cons 'markdown-match-heading-5-atx '((1 markdown-header-delimiter-face)
1855 (2 markdown-header-face-5)
1856 (3 markdown-header-delimiter-face)))
1857 (cons 'markdown-match-heading-4-atx '((1 markdown-header-delimiter-face)
1858 (2 markdown-header-face-4)
1859 (3 markdown-header-delimiter-face)))
1860 (cons 'markdown-match-heading-3-atx '((1 markdown-header-delimiter-face)
1861 (2 markdown-header-face-3)
1862 (3 markdown-header-delimiter-face)))
1863 (cons 'markdown-match-heading-2-atx '((1 markdown-header-delimiter-face)
1864 (2 markdown-header-face-2)
1865 (3 markdown-header-delimiter-face)))
1866 (cons 'markdown-match-heading-1-atx '((1 markdown-header-delimiter-face)
1867 (2 markdown-header-face-1)
1868 (3 markdown-header-delimiter-face)))
1869 (cons 'markdown-match-multimarkdown-metadata '((1 markdown-metadata-key-face)
1870 (2 markdown-markup-face)
1871 (3 markdown-metadata-value-face)))
1872 (cons 'markdown-match-pandoc-metadata '((1 markdown-markup-face)
1873 (2 markdown-markup-face)
1874 (3 markdown-metadata-value-face)))
1875 (cons 'markdown-match-hr 'markdown-header-delimiter-face)
1876 (cons 'markdown-match-code '((1 markdown-markup-face)
1877 (2 markdown-inline-code-face)
1878 (3 markdown-markup-face)))
1879 (cons markdown-regex-kbd '((1 markdown-markup-face)
1880 (2 markdown-inline-code-face)
1881 (3 markdown-markup-face)))
1882 (cons markdown-regex-angle-uri '((1 markdown-markup-face)
1883 (2 markdown-link-face)
1884 (3 markdown-markup-face)))
1885 (cons markdown-regex-list '(2 markdown-list-face))
1886 (cons markdown-regex-footnote '((1 markdown-markup-face) ; [^
1887 (2 markdown-footnote-face) ; label
1888 (3 markdown-markup-face))) ; ]
1889 (cons markdown-regex-link-inline '((1 markdown-markup-face nil t) ; ! (optional)
1890 (2 markdown-markup-face) ; [
1891 (3 markdown-link-face) ; text
1892 (4 markdown-markup-face) ; ]
1893 (5 markdown-markup-face) ; (
1894 (6 markdown-url-face) ; url
1895 (7 markdown-link-title-face nil t) ; "title" (optional)
1896 (8 markdown-markup-face))) ; )
1897 (cons markdown-regex-link-reference '((1 markdown-markup-face nil t) ; ! (optional)
1898 (2 markdown-markup-face) ; [
1899 (3 markdown-link-face) ; text
1900 (4 markdown-markup-face) ; ]
1901 (5 markdown-markup-face) ; [
1902 (6 markdown-reference-face) ; label
1903 (7 markdown-markup-face))) ; ]
1904 (cons markdown-regex-reference-definition '((1 markdown-markup-face) ; [
1905 (2 markdown-reference-face) ; label
1906 (3 markdown-markup-face) ; ]
1907 (4 markdown-markup-face) ; :
1908 (5 markdown-url-face) ; url
1909 (6 markdown-link-title-face))) ; "title" (optional)
1910 ;; Math mode $..$
1911 (cons 'markdown-match-math-single '((1 markdown-markup-face prepend)
1912 (2 markdown-math-face append)
1913 (3 markdown-markup-face prepend)))
1914 ;; Math mode $$..$$
1915 (cons 'markdown-match-math-double '((1 markdown-markup-face prepend)
1916 (2 markdown-math-face append)
1917 (3 markdown-markup-face prepend)))
1918 (cons 'markdown-match-bold '((1 markdown-markup-face prepend)
1919 (2 markdown-bold-face append)
1920 (3 markdown-markup-face prepend)))
1921 (cons 'markdown-match-italic '((1 markdown-markup-face prepend)
1922 (2 markdown-italic-face append)
1923 (3 markdown-markup-face prepend)))
1924 (cons markdown-regex-uri 'markdown-link-face)
1925 (cons markdown-regex-email 'markdown-link-face)
1926 (cons markdown-regex-line-break '(1 markdown-line-break-face prepend))
1928 "Syntax highlighting for Markdown files.")
1930 (defconst markdown-mode-font-lock-keywords-math
1931 (list
1932 ;; Display mode equations with brackets: \[ \]
1933 (cons markdown-regex-math-display '((1 markdown-markup-face prepend)
1934 (2 markdown-math-face append)
1935 (3 markdown-markup-face prepend)))
1936 ;; Equation reference (eq:foo)
1937 (cons "\\((eq:\\)\\([[:alnum:]:_]+\\)\\()\\)" '((1 markdown-markup-face)
1938 (2 markdown-reference-face)
1939 (3 markdown-markup-face)))
1940 ;; Equation reference \eqref{foo}
1941 (cons "\\(\\\\eqref{\\)\\([[:alnum:]:_]+\\)\\(}\\)" '((1 markdown-markup-face)
1942 (2 markdown-reference-face)
1943 (3 markdown-markup-face))))
1944 "Syntax highlighting for LaTeX and itex fragments.")
1946 (defvar markdown-mode-font-lock-keywords nil
1947 "Default highlighting expressions for Markdown mode.
1948 This variable is defined as a buffer-local variable for dynamic
1949 extension support.")
1951 ;; Footnotes
1952 (defvar markdown-footnote-counter 0
1953 "Counter for footnote numbers.")
1954 (make-variable-buffer-local 'markdown-footnote-counter)
1956 (defconst markdown-footnote-chars
1957 "[[:alnum:]-]"
1958 "Regular expression maching any character that is allowed in a footnote identifier.")
1960 (defconst markdown-regex-footnote-definition
1961 (concat "^\\[\\(\\^" markdown-footnote-chars "*?\\)\\]:\\(?:[ \t]+\\|$\\)")
1962 "Regular expression matching a footnote definition, capturing the label.")
1965 ;;; Compatibility =============================================================
1967 (defun markdown-replace-regexp-in-string (regexp rep string)
1968 "Replace ocurrences of REGEXP with REP in STRING.
1969 This is a compatibility wrapper to provide `replace-regexp-in-string'
1970 in XEmacs 21."
1971 (if (featurep 'xemacs)
1972 (replace-in-string string regexp rep)
1973 (replace-regexp-in-string regexp rep string)))
1975 ;; `markdown-use-region-p' is a compatibility function which checks
1976 ;; for an active region, with fallbacks for older Emacsen and XEmacs.
1977 (eval-and-compile
1978 (cond
1979 ;; Emacs 23 and newer
1980 ((fboundp 'use-region-p)
1981 (defalias 'markdown-use-region-p 'use-region-p))
1982 ;; Older Emacsen
1983 ((and (boundp 'transient-mark-mode) (boundp 'mark-active))
1984 (defun markdown-use-region-p ()
1985 "Compatibility wrapper to provide `use-region-p'."
1986 (and transient-mark-mode mark-active)))
1987 ;; XEmacs
1988 ((fboundp 'region-active-p)
1989 (defalias 'markdown-use-region-p 'region-active-p))))
1991 (defun markdown-use-buttons-p ()
1992 "Determine whether this Emacs supports buttons."
1993 (or (featurep 'button) (locate-library "button")))
1995 ;; Use new names for outline-mode functions in Emacs 25 and later.
1996 (eval-and-compile
1997 (defalias 'markdown-hide-sublevels
1998 (if (fboundp 'outline-hide-sublevels)
1999 'outline-hide-sublevels
2000 'hide-sublevels))
2001 (defalias 'markdown-show-all
2002 (if (fboundp 'outline-show-all)
2003 'outline-show-all
2004 'show-all))
2005 (defalias 'markdown-hide-body
2006 (if (fboundp 'outline-hide-body)
2007 'outline-hide-body
2008 'hide-body))
2009 (defalias 'markdown-show-children
2010 (if (fboundp 'outline-show-children)
2011 'outline-show-children
2012 'show-children))
2013 (defalias 'markdown-show-subtree
2014 (if (fboundp 'outline-show-subtree)
2015 'outline-show-subtree
2016 'show-subtree))
2017 (defalias 'markdown-hide-subtree
2018 (if (fboundp 'outline-hide-subtree)
2019 'outline-hide-subtree
2020 'hide-subtree)))
2023 ;;; Markdown Parsing Functions ================================================
2025 (defun markdown-cur-line-blank-p ()
2026 "Return t if the current line is blank and nil otherwise."
2027 (save-match-data
2028 (save-excursion
2029 (beginning-of-line)
2030 (re-search-forward "^\\s *$" (line-end-position) t))))
2032 (defun markdown-prev-line-blank-p ()
2033 "Return t if the previous line is blank and nil otherwise.
2034 If we are at the first line, then consider the previous line to be blank."
2035 (or (= (line-beginning-position) (point-min))
2036 (save-excursion
2037 (forward-line -1)
2038 (markdown-cur-line-blank-p))))
2040 (defun markdown-next-line-blank-p ()
2041 "Return t if the next line is blank and nil otherwise.
2042 If we are at the last line, then consider the next line to be blank."
2043 (or (= (line-end-position) (point-max))
2044 (save-excursion
2045 (forward-line 1)
2046 (markdown-cur-line-blank-p))))
2048 (defun markdown-prev-line-indent-p ()
2049 "Return t if the previous line is indented and nil otherwise."
2050 (save-excursion
2051 (if (= (line-beginning-position) (point-min))
2053 (forward-line -1)
2054 (goto-char (line-beginning-position))
2055 (if (re-search-forward "^\\s " (line-end-position) t) t))))
2057 (defun markdown-cur-line-indent ()
2058 "Return the number of leading whitespace characters in the current line."
2059 (save-match-data
2060 (save-excursion
2061 (goto-char (line-beginning-position))
2062 (re-search-forward "^[ \t]+" (line-end-position) t)
2063 (current-column))))
2065 (defun markdown-prev-line-indent ()
2066 "Return the number of leading whitespace characters in the previous line.
2067 Return 0 if the current line is the first line in the buffer."
2068 (save-excursion
2069 (if (= (line-beginning-position) (point-min))
2071 (forward-line -1)
2072 (markdown-cur-line-indent))))
2074 (defun markdown-next-line-indent ()
2075 "Return the number of leading whitespace characters in the next line.
2076 Return 0 if line is the last line in the buffer."
2077 (save-excursion
2078 (if (= (line-end-position) (point-max))
2080 (forward-line 1)
2081 (markdown-cur-line-indent))))
2083 (defun markdown-cur-non-list-indent ()
2084 "Return beginning position of list item text (not including the list marker).
2085 Return nil if the current line is not the beginning of a list item."
2086 (save-match-data
2087 (save-excursion
2088 (beginning-of-line)
2089 (when (re-search-forward markdown-regex-list (line-end-position) t)
2090 (current-column)))))
2092 (defun markdown-prev-non-list-indent ()
2093 "Return position of the first non-list-marker on the previous line."
2094 (save-excursion
2095 (forward-line -1)
2096 (markdown-cur-non-list-indent)))
2098 (defun markdown-new-baseline-p ()
2099 "Determine if the current line begins a new baseline level."
2100 (save-excursion
2101 (beginning-of-line)
2102 (save-match-data
2103 (or (looking-at markdown-regex-header)
2104 (looking-at markdown-regex-hr)
2105 (and (null (markdown-cur-non-list-indent))
2106 (= (markdown-cur-line-indent) 0)
2107 (markdown-prev-line-blank-p))))))
2109 (defun markdown-search-backward-baseline ()
2110 "Search backward baseline point with no indentation and not a list item."
2111 (end-of-line)
2112 (let (stop)
2113 (while (not (or stop (bobp)))
2114 (re-search-backward markdown-regex-block-separator nil t)
2115 (when (match-end 2)
2116 (goto-char (match-end 2))
2117 (cond
2118 ((markdown-new-baseline-p)
2119 (setq stop t))
2120 ((looking-at markdown-regex-list)
2121 (setq stop nil))
2122 (t (setq stop t)))))))
2124 (defun markdown-update-list-levels (marker indent levels)
2125 "Update list levels given list MARKER, block INDENT, and current LEVELS.
2126 Here, MARKER is a string representing the type of list, INDENT is an integer
2127 giving the indentation, in spaces, of the current block, and LEVELS is a
2128 list of the indentation levels of parent list items. When LEVELS is nil,
2129 it means we are at baseline (not inside of a nested list)."
2130 (cond
2131 ;; New list item at baseline.
2132 ((and marker (null levels))
2133 (setq levels (list indent)))
2134 ;; List item with greater indentation (four or more spaces).
2135 ;; Increase list level.
2136 ((and marker (>= indent (+ (car levels) 4)))
2137 (setq levels (cons indent levels)))
2138 ;; List item with greater or equal indentation (less than four spaces).
2139 ;; Do not increase list level.
2140 ((and marker (>= indent (car levels)))
2141 levels)
2142 ;; Lesser indentation level.
2143 ;; Pop appropriate number of elements off LEVELS list (e.g., lesser
2144 ;; indentation could move back more than one list level). Note
2145 ;; that this block need not be the beginning of list item.
2146 ((< indent (car levels))
2147 (while (and (> (length levels) 1)
2148 (< indent (+ (cadr levels) 4)))
2149 (setq levels (cdr levels)))
2150 levels)
2151 ;; Otherwise, do nothing.
2152 (t levels)))
2154 (defun markdown-calculate-list-levels ()
2155 "Calculate list levels at point.
2156 Return a list of the form (n1 n2 n3 ...) where n1 is the
2157 indentation of the deepest nested list item in the branch of
2158 the list at the point, n2 is the indentation of the parent
2159 list item, and so on. The depth of the list item is therefore
2160 the length of the returned list. If the point is not at or
2161 immediately after a list item, return nil."
2162 (save-excursion
2163 (let ((first (point)) levels indent pre-regexp)
2164 ;; Find a baseline point with zero list indentation
2165 (markdown-search-backward-baseline)
2166 ;; Search for all list items between baseline and LOC
2167 (while (and (< (point) first)
2168 (re-search-forward markdown-regex-list first t))
2169 (setq pre-regexp (format "^\\( \\|\t\\)\\{%d\\}" (1+ (length levels))))
2170 (beginning-of-line)
2171 (cond
2172 ;; Make sure this is not a header or hr
2173 ((markdown-new-baseline-p) (setq levels nil))
2174 ;; Make sure this is not a line from a pre block
2175 ((looking-at pre-regexp))
2176 ;; If not, then update levels
2178 (setq indent (markdown-cur-line-indent))
2179 (setq levels (markdown-update-list-levels (match-string 2)
2180 indent levels))))
2181 (end-of-line))
2182 levels)))
2184 (defun markdown-prev-list-item (level)
2185 "Search backward from point for a list item with indentation LEVEL.
2186 Set point to the beginning of the item, and return point, or nil
2187 upon failure."
2188 (let (bounds indent prev)
2189 (setq prev (point))
2190 (forward-line -1)
2191 (setq indent (markdown-cur-line-indent))
2192 (while
2193 (cond
2194 ;; List item
2195 ((and (looking-at markdown-regex-list)
2196 (setq bounds (markdown-cur-list-item-bounds)))
2197 (cond
2198 ;; Stop and return point at item of lesser or equal indentation
2199 ((<= (nth 3 bounds) level)
2200 (setq prev (point))
2201 nil)
2202 ;; Stop at beginning of buffer
2203 ((bobp) (setq prev nil))
2204 ;; Continue at item with greater indentation
2205 ((> (nth 3 bounds) level) t)))
2206 ;; Stop at beginning of buffer
2207 ((bobp) (setq prev nil))
2208 ;; Continue if current line is blank
2209 ((markdown-cur-line-blank-p) t)
2210 ;; Continue while indentation is the same or greater
2211 ((>= indent level) t)
2212 ;; Stop if current indentation is less than list item
2213 ;; and the next is blank
2214 ((and (< indent level)
2215 (markdown-next-line-blank-p))
2216 (setq prev nil))
2217 ;; Stop at a header
2218 ((looking-at markdown-regex-header) (setq prev nil))
2219 ;; Stop at a horizontal rule
2220 ((looking-at markdown-regex-hr) (setq prev nil))
2221 ;; Otherwise, continue.
2222 (t t))
2223 (forward-line -1)
2224 (setq indent (markdown-cur-line-indent)))
2225 prev))
2227 (defun markdown-next-list-item (level)
2228 "Search forward from point for the next list item with indentation LEVEL.
2229 Set point to the beginning of the item, and return point, or nil
2230 upon failure."
2231 (let (bounds indent prev next)
2232 (setq next (point))
2233 (forward-line)
2234 (setq indent (markdown-cur-line-indent))
2235 (while
2236 (cond
2237 ;; Stop at end of the buffer.
2238 ((eobp) (setq prev nil))
2239 ;; Continue if the current line is blank
2240 ((markdown-cur-line-blank-p) t)
2241 ;; List item
2242 ((and (looking-at markdown-regex-list)
2243 (setq bounds (markdown-cur-list-item-bounds)))
2244 (cond
2245 ;; Continue at item with greater indentation
2246 ((> (nth 3 bounds) level) t)
2247 ;; Stop and return point at item of equal indentation
2248 ((= (nth 3 bounds) level)
2249 (setq next (point))
2250 nil)
2251 ;; Stop and return nil at item with lesser indentation
2252 ((< (nth 3 bounds) level)
2253 (setq next nil)
2254 nil)))
2255 ;; Continue while indentation is the same or greater
2256 ((>= indent level) t)
2257 ;; Stop if current indentation is less than list item
2258 ;; and the previous line was blank.
2259 ((and (< indent level)
2260 (markdown-prev-line-blank-p))
2261 (setq next nil))
2262 ;; Stop at a header
2263 ((looking-at markdown-regex-header) (setq next nil))
2264 ;; Stop at a horizontal rule
2265 ((looking-at markdown-regex-hr) (setq next nil))
2266 ;; Otherwise, continue.
2267 (t t))
2268 (forward-line)
2269 (setq indent (markdown-cur-line-indent)))
2270 next))
2272 (defun markdown-cur-list-item-end (level)
2273 "Move to the end of the current list item with nonlist indentation LEVEL.
2274 If the point is not in a list item, do nothing."
2275 (let (indent)
2276 (forward-line)
2277 (setq indent (markdown-cur-line-indent))
2278 (while
2279 (cond
2280 ;; Stop at end of the buffer.
2281 ((eobp) nil)
2282 ;; Continue if the current line is blank
2283 ((markdown-cur-line-blank-p) t)
2284 ;; Continue while indentation is the same or greater
2285 ((>= indent level) t)
2286 ;; Stop if current indentation is less than list item
2287 ;; and the previous line was blank.
2288 ((and (< indent level)
2289 (markdown-prev-line-blank-p))
2290 nil)
2291 ;; Stop at a new list item of the same or lesser indentation
2292 ((looking-at markdown-regex-list) nil)
2293 ;; Stop at a header
2294 ((looking-at markdown-regex-header) nil)
2295 ;; Stop at a horizontal rule
2296 ((looking-at markdown-regex-hr) nil)
2297 ;; Otherwise, continue.
2298 (t t))
2299 (forward-line)
2300 (setq indent (markdown-cur-line-indent)))
2301 ;; Don't skip over whitespace for empty list items (marker and
2302 ;; whitespace only), just move to end of whitespace.
2303 (if (looking-back (concat markdown-regex-list "\\s-*") nil)
2304 (goto-char (match-end 3))
2305 (skip-syntax-backward "-"))))
2307 (defun markdown-cur-list-item-bounds ()
2308 "Return bounds and indentation of the current list item.
2309 Return a list of the form (begin end indent nonlist-indent marker).
2310 If the point is not inside a list item, return nil.
2311 Leave match data intact for `markdown-regex-list'."
2312 (let (cur prev-begin prev-end indent nonlist-indent marker)
2313 ;; Store current location
2314 (setq cur (point))
2315 ;; Verify that cur is between beginning and end of item
2316 (save-excursion
2317 (end-of-line)
2318 (when (re-search-backward markdown-regex-list nil t)
2319 (setq prev-begin (match-beginning 0))
2320 (setq indent (length (match-string 1)))
2321 (setq nonlist-indent (length (match-string 0)))
2322 (setq marker (concat (match-string 2) (match-string 3)))
2323 (save-match-data
2324 (markdown-cur-list-item-end nonlist-indent)
2325 (setq prev-end (point)))
2326 (when (and (>= cur prev-begin)
2327 (<= cur prev-end)
2328 nonlist-indent)
2329 (list prev-begin prev-end indent nonlist-indent marker))))))
2331 (defun markdown-bounds-of-thing-at-point (thing)
2332 "Call `bounds-of-thing-at-point' for THING with slight modifications.
2333 Does not include trailing newlines when THING is 'line. Handles the
2334 end of buffer case by setting both endpoints equal to the value of
2335 `point-max', since an empty region will trigger empty markup insertion.
2336 Return bounds of form (beg . end) if THING is found, or nil otherwise."
2337 (let* ((bounds (bounds-of-thing-at-point thing))
2338 (a (car bounds))
2339 (b (cdr bounds)))
2340 (when bounds
2341 (when (eq thing 'line)
2342 (cond ((and (eobp) (markdown-cur-line-blank-p))
2343 (setq a b))
2344 ((char-equal (char-before b) ?\^J)
2345 (setq b (1- b)))))
2346 (cons a b))))
2348 (defun markdown-reference-definition (reference)
2349 "Find out whether Markdown REFERENCE is defined.
2350 REFERENCE should not include the square brackets.
2351 When REFERENCE is defined, return a list of the form (text start end)
2352 containing the definition text itself followed by the start and end
2353 locations of the text. Otherwise, return nil.
2354 Leave match data for `markdown-regex-reference-definition'
2355 intact additional processing."
2356 (let ((reference (downcase reference)))
2357 (save-excursion
2358 (goto-char (point-min))
2359 (catch 'found
2360 (while (re-search-forward markdown-regex-reference-definition nil t)
2361 (when (string= reference (downcase (match-string-no-properties 2)))
2362 (throw 'found
2363 (list (match-string-no-properties 5)
2364 (match-beginning 5) (match-end 5)))))))))
2366 (defun markdown-get-defined-references ()
2367 "Return a list of all defined reference labels (not including square brackets)."
2368 (save-excursion
2369 (goto-char (point-min))
2370 (let (refs)
2371 (while (re-search-forward markdown-regex-reference-definition nil t)
2372 (let ((target (match-string-no-properties 2)))
2373 (add-to-list 'refs target t)))
2374 refs)))
2376 (defun markdown-code-at-point-p ()
2377 "Return non-nil if the point is at an inline code fragment.
2378 Return nil otherwise. Set match data according to
2379 `markdown-match-code' upon success.
2380 This function searches the block for a code fragment that
2381 contains the point using `markdown-match-code'. We do this
2382 because `thing-at-point-looking-at' does not work reliably with
2383 `markdown-regex-code'.
2385 The match data is set as follows:
2386 Group 1 matches the opening backticks.
2387 Group 2 matches the code fragment itself, without backticks.
2388 Group 3 matches the closing backticks."
2389 (interactive)
2390 (save-excursion
2391 (let ((old-point (point))
2392 (end-of-block (progn (markdown-end-of-block) (point)))
2393 found)
2394 (markdown-beginning-of-block)
2395 (while (and (markdown-match-code end-of-block)
2396 (setq found t)
2397 (< (match-end 0) old-point)))
2398 (and found ; matched something
2399 (<= (match-beginning 0) old-point) ; match contains old-point
2400 (>= (match-end 0) old-point)))))
2402 (defun markdown-code-block-at-pos (pos)
2403 "Return match data list if there is a code block at POS.
2404 This includes pre blocks, tilde-fenced code blocks, and GFM
2405 quoted code blocks. Return nil otherwise."
2406 (or (get-text-property pos 'markdown-pre)
2407 (get-text-property pos 'markdown-gfm-code)
2408 (get-text-property pos 'markdown-fenced-code)
2409 ;; polymode removes text properties set by markdown-mode, so
2410 ;; check if `poly-markdown-mode' is active and whether the
2411 ;; `chunkmode' property is non-nil at POS.
2412 (and (bound-and-true-p poly-markdown-mode)
2413 (get-text-property pos 'chunkmode))))
2415 (defun markdown-code-block-at-point ()
2416 "Return match data if the point is inside a code block.
2417 This includes pre blocks, tilde-fenced code blocks, and
2418 GFM quoted code blocks. Calls `markdown-code-block-at-pos'."
2419 (markdown-code-block-at-pos (point)))
2422 ;;; Markdown Font Lock Matching Functions =====================================
2424 (defun markdown-range-property-any (begin end prop values)
2425 "Return t if PROP from BEGIN to END is equal to one of the given VALUES.
2426 Also returns t if PROP is a list containing one of the VALUES.
2427 Return nil otherwise."
2428 (let (loc props val)
2429 (catch 'found
2430 (dolist (loc (number-sequence begin end))
2431 (when (setq props (get-char-property loc prop))
2432 (cond ((listp props)
2433 ;; props is a list, check for membership
2434 (dolist (val values)
2435 (when (memq val props) (throw 'found loc))))
2437 ;; props is a scalar, check for equality
2438 (dolist (val values)
2439 (when (eq val props) (throw 'found loc))))))))))
2441 (defun markdown-match-inline-generic (regex last)
2442 "Match inline REGEX from the point to LAST."
2443 (when (re-search-forward regex last t)
2444 (let ((bounds (markdown-code-block-at-pos (match-beginning 0))))
2445 (if (null bounds)
2446 ;; Not in a code block: keep match data and return t when in bounds
2447 (<= (match-end 0) last)
2448 ;; In code block: move past it and recursively search again
2449 (when (< (goto-char (nth 1 bounds)) last)
2450 (markdown-match-inline-generic regex last))))))
2452 (defun markdown-match-code (last)
2453 "Match inline code fragments from point to LAST."
2454 (unless (bobp)
2455 (backward-char 1))
2456 (when (markdown-match-inline-generic markdown-regex-code last)
2457 (set-match-data (list (match-beginning 1) (match-end 1)
2458 (match-beginning 2) (match-end 2)
2459 (match-beginning 3) (match-end 3)
2460 (match-beginning 4) (match-end 4)))
2461 (goto-char (1+ (match-end 0)))))
2463 (defun markdown-match-bold (last)
2464 "Match inline bold from the point to LAST."
2465 (when (markdown-match-inline-generic markdown-regex-bold last)
2466 (set-match-data (list (match-beginning 2) (match-end 2)
2467 (match-beginning 3) (match-end 3)
2468 (match-beginning 4) (match-end 4)
2469 (match-beginning 5) (match-end 5)))
2470 (goto-char (1+ (match-end 0)))))
2472 (defun markdown-match-italic (last)
2473 "Match inline italics from the point to LAST."
2474 (let ((regex (if (eq major-mode 'gfm-mode)
2475 markdown-regex-gfm-italic markdown-regex-italic)))
2476 (when (markdown-match-inline-generic regex last)
2477 (let ((begin (match-beginning 1)) (end (match-end 1)))
2478 (cond
2479 ((markdown-range-property-any
2480 begin end 'face (list markdown-inline-code-face
2481 markdown-bold-face
2482 markdown-list-face
2483 markdown-math-face))
2484 (goto-char (1+ (match-end 0)))
2485 (markdown-match-italic last))
2487 (set-match-data (list (match-beginning 1) (match-end 1)
2488 (match-beginning 2) (match-end 2)
2489 (match-beginning 3) (match-end 3)
2490 (match-beginning 4) (match-end 4)))
2491 (goto-char (1+ (match-end 0)))))))))
2493 (defun markdown-match-math-generic (regex last)
2494 "Match quoted $..$ or $$..$$ math from point to LAST."
2495 (when (and markdown-enable-math
2496 (markdown-match-inline-generic regex last))
2497 (let ((begin (match-beginning 1)) (end (match-end 1)))
2498 (prog1
2499 (if (markdown-range-property-any
2500 begin end 'face (list markdown-inline-code-face
2501 markdown-bold-face))
2502 (markdown-match-math-generic regex last)
2504 (goto-char (1+ (match-end 0)))))))
2506 (defun markdown-match-math-single (last)
2507 "Match single quoted $..$ math from point to LAST."
2508 (markdown-match-math-generic markdown-regex-math-inline-single last))
2510 (defun markdown-match-math-double (last)
2511 "Match double quoted $$..$$ math from point to LAST."
2512 (markdown-match-math-generic markdown-regex-math-inline-double last))
2514 (defun markdown-match-propertized-text (property last)
2515 "Match text with PROPERTY from point to LAST.
2516 Restore match data previously stored in PROPERTY."
2517 (let (saved pos)
2518 (unless (setq saved (get-text-property (point) property))
2519 (setq pos (next-single-char-property-change (point) property nil last))
2520 (setq saved (get-text-property pos property)))
2521 (when saved
2522 (set-match-data saved)
2523 (goto-char (min (1+ (match-end 0)) (point-max)))
2524 saved)))
2526 (defun markdown-match-pre-blocks (last)
2527 "Match preformatted blocks from point to LAST.
2528 Use data stored in 'markdown-pre text property during syntax
2529 analysis."
2530 (markdown-match-propertized-text 'markdown-pre last))
2532 (defun markdown-match-gfm-code-blocks (last)
2533 "Match GFM quoted code blocks from point to LAST.
2534 Use data stored in 'markdown-gfm-code text property during syntax
2535 analysis."
2536 (markdown-match-propertized-text 'markdown-gfm-code last))
2538 (defun markdown-match-fenced-code-blocks (last)
2539 "Match fenced code blocks from the point to LAST."
2540 (markdown-match-propertized-text 'markdown-fenced-code last))
2542 (defun markdown-match-blockquotes (last)
2543 "Match blockquotes from point to LAST.
2544 Use data stored in 'markdown-blockquote text property during syntax
2545 analysis."
2546 (markdown-match-propertized-text 'markdown-blockquote last))
2548 (defun markdown-match-heading-1-setext (last)
2549 "Match level 1 setext headings from point to LAST."
2550 (markdown-match-propertized-text 'markdown-heading-1-setext last))
2552 (defun markdown-match-heading-2-setext (last)
2553 "Match level 2 setext headings from point to LAST."
2554 (markdown-match-propertized-text 'markdown-heading-2-setext last))
2556 (defun markdown-match-heading-1-atx (last)
2557 "Match level 1 ATX headings from point to LAST."
2558 (markdown-match-propertized-text 'markdown-heading-1-atx last))
2560 (defun markdown-match-heading-2-atx (last)
2561 "Match level 2 ATX headings from point to LAST."
2562 (markdown-match-propertized-text 'markdown-heading-2-atx last))
2564 (defun markdown-match-heading-3-atx (last)
2565 "Match level 3 ATX headings from point to LAST."
2566 (markdown-match-propertized-text 'markdown-heading-3-atx last))
2568 (defun markdown-match-heading-4-atx (last)
2569 "Match level 4 ATX headings from point to LAST."
2570 (markdown-match-propertized-text 'markdown-heading-4-atx last))
2572 (defun markdown-match-heading-5-atx (last)
2573 "Match level 5 ATX headings from point to LAST."
2574 (markdown-match-propertized-text 'markdown-heading-5-atx last))
2576 (defun markdown-match-heading-6-atx (last)
2577 "Match level 6 ATX headings from point to LAST."
2578 (markdown-match-propertized-text 'markdown-heading-6-atx last))
2580 (defun markdown-match-hr (last)
2581 "Match horizontal rules comments from the point to LAST."
2582 (while (and (re-search-forward markdown-regex-hr last t)
2583 (or (markdown-on-heading-p)
2584 (markdown-code-block-at-point))
2585 (< (match-end 0) last))
2586 (forward-line))
2587 (beginning-of-line)
2588 (cond ((looking-at markdown-regex-hr)
2589 (forward-line)
2591 (t nil)))
2593 (defun markdown-match-comments (last)
2594 "Match HTML comments from the point to LAST."
2595 (when (and (skip-syntax-forward "^<" last))
2596 (let ((beg (point)))
2597 (when (and (skip-syntax-forward "^>" last) (< (point) last))
2598 (forward-char)
2599 (set-match-data (list beg (point)))
2600 t))))
2602 (defun markdown-match-generic-metadata (regexp last)
2603 "Match generic metadata specified by REGEXP from the point to LAST."
2604 (let ((header-end (save-excursion
2605 (goto-char (point-min))
2606 (if (re-search-forward "\n\n" (point-max) t)
2607 (match-beginning 0)
2608 (point-max)))))
2609 (cond ((>= (point) header-end)
2610 ;; Don't match anything outside of the header.
2611 nil)
2612 ((re-search-forward regexp (min last header-end) t)
2613 ;; If a metadata item is found, it may span several lines.
2614 (let ((key-beginning (match-beginning 1))
2615 (key-end (match-end 1))
2616 (markup-begin (match-beginning 2))
2617 (markup-end (match-end 2))
2618 (value-beginning (match-beginning 3)))
2619 (while (and (not (looking-at regexp))
2620 (not (> (point) (min last header-end)))
2621 (not (eobp)))
2622 (forward-line))
2623 (unless (eobp)
2624 (forward-line -1)
2625 (end-of-line))
2626 (set-match-data (list key-beginning (point) ; complete metadata
2627 key-beginning key-end ; key
2628 markup-begin markup-end ; markup
2629 value-beginning (point))) ; value
2631 (t nil))))
2633 (defun markdown-match-multimarkdown-metadata (last)
2634 "Match MultiMarkdown metadata from the point to LAST."
2635 (markdown-match-generic-metadata markdown-regex-multimarkdown-metadata last))
2637 (defun markdown-match-pandoc-metadata (last)
2638 "Match Pandoc metadata from the point to LAST."
2639 (markdown-match-generic-metadata markdown-regex-pandoc-metadata last))
2642 ;;; Syntax Table ==============================================================
2644 (defvar markdown-mode-syntax-table
2645 (let ((tab (make-syntax-table text-mode-syntax-table)))
2646 (modify-syntax-entry ?\" "." tab)
2647 tab)
2648 "Syntax table for `markdown-mode'.")
2651 ;;; Element Insertion =========================================================
2653 (defun markdown-ensure-blank-line-before ()
2654 "If previous line is not already blank, insert a blank line before point."
2655 (unless (bolp) (insert "\n"))
2656 (unless (or (bobp) (looking-back "\n\\s-*\n" nil)) (insert "\n")))
2658 (defun markdown-ensure-blank-line-after ()
2659 "If following line is not already blank, insert a blank line after point.
2660 Return the point where it was originally."
2661 (save-excursion
2662 (unless (eolp) (insert "\n"))
2663 (unless (or (eobp) (looking-at "\n\\s-*\n")) (insert "\n"))))
2665 (defun markdown-wrap-or-insert (s1 s2 &optional thing beg end)
2666 "Insert the strings S1 and S2, wrapping around region or THING.
2667 If a region is specified by the optional BEG and END arguments,
2668 wrap the strings S1 and S2 around that region.
2669 If there is an active region, wrap the strings S1 and S2 around
2670 the region. If there is not an active region but the point is at
2671 THING, wrap that thing (which defaults to word). Otherwise, just
2672 insert S1 and S2 and place the cursor in between. Return the
2673 bounds of the entire wrapped string, or nil if nothing was wrapped
2674 and S1 and S2 were only inserted."
2675 (let (a b bounds new-point)
2676 (cond
2677 ;; Given region
2678 ((and beg end)
2679 (setq a beg
2680 b end
2681 new-point (+ (point) (length s1))))
2682 ;; Active region
2683 ((markdown-use-region-p)
2684 (setq a (region-beginning)
2685 b (region-end)
2686 new-point (+ (point) (length s1))))
2687 ;; Thing (word) at point
2688 ((setq bounds (markdown-bounds-of-thing-at-point (or thing 'word)))
2689 (setq a (car bounds)
2690 b (cdr bounds)
2691 new-point (+ (point) (length s1))))
2692 ;; No active region and no word
2694 (setq a (point)
2695 b (point))))
2696 (goto-char b)
2697 (insert s2)
2698 (goto-char a)
2699 (insert s1)
2700 (when new-point (goto-char new-point))
2701 (if (= a b)
2703 (setq b (+ b (length s1) (length s2)))
2704 (cons a b))))
2706 (defun markdown-point-after-unwrap (cur prefix suffix)
2707 "Return desired position of point after an unwrapping operation.
2708 CUR gives the position of the point before the operation.
2709 Additionally, two cons cells must be provided. PREFIX gives the
2710 bounds of the prefix string and SUFFIX gives the bounds of the
2711 suffix string."
2712 (cond ((< cur (cdr prefix)) (car prefix))
2713 ((< cur (car suffix)) (- cur (- (cdr prefix) (car prefix))))
2714 ((<= cur (cdr suffix))
2715 (- cur (+ (- (cdr prefix) (car prefix))
2716 (- cur (car suffix)))))
2717 (t cur)))
2719 (defun markdown-unwrap-thing-at-point (regexp all text)
2720 "Remove prefix and suffix of thing at point and reposition the point.
2721 When the thing at point matches REGEXP, replace the subexpression
2722 ALL with the string in subexpression TEXT. Reposition the point
2723 in an appropriate location accounting for the removal of prefix
2724 and suffix strings. Return new bounds of string from group TEXT.
2725 When REGEXP is nil, assumes match data is already set."
2726 (when (or (null regexp)
2727 (thing-at-point-looking-at regexp))
2728 (let ((cur (point))
2729 (prefix (cons (match-beginning all) (match-beginning text)))
2730 (suffix (cons (match-end text) (match-end all)))
2731 (bounds (cons (match-beginning text) (match-end text))))
2732 ;; Replace the thing at point
2733 (replace-match (match-string text) t t nil all)
2734 ;; Reposition the point
2735 (goto-char (markdown-point-after-unwrap cur prefix suffix))
2736 ;; Adjust bounds
2737 (setq bounds (cons (car prefix)
2738 (- (cdr bounds) (- (cdr prefix) (car prefix))))))))
2740 (defun markdown-unwrap-things-in-region (beg end regexp all text)
2741 "Remove prefix and suffix of all things in region from BEG to END.
2742 When a thing in the region matches REGEXP, replace the
2743 subexpression ALL with the string in subexpression TEXT.
2744 Return a cons cell containing updated bounds for the region."
2745 (save-excursion
2746 (goto-char beg)
2747 (let ((removed 0) len-all len-text)
2748 (while (re-search-forward regexp (- end removed) t)
2749 (setq len-all (length (match-string-no-properties all)))
2750 (setq len-text (length (match-string-no-properties text)))
2751 (setq removed (+ removed (- len-all len-text)))
2752 (replace-match (match-string text) t t nil all))
2753 (cons beg (- end removed)))))
2755 (defun markdown-insert-hr (arg)
2756 "Insert or replace a horizonal rule.
2757 By default, use the first element of `markdown-hr-strings'. When
2758 ARG is non-nil, as when given a prefix, select a different
2759 element as follows. When prefixed with \\[universal-argument],
2760 use the last element of `markdown-hr-strings' instead. When
2761 prefixed with an integer from 1 to the length of
2762 `markdown-hr-strings', use the element in that position instead."
2763 (interactive "*P")
2764 (when (thing-at-point-looking-at markdown-regex-hr)
2765 (delete-region (match-beginning 0) (match-end 0)))
2766 (markdown-ensure-blank-line-before)
2767 (cond ((equal arg '(4))
2768 (insert (car (reverse markdown-hr-strings))))
2769 ((and (integerp arg) (> arg 0)
2770 (<= arg (length markdown-hr-strings)))
2771 (insert (nth (1- arg) markdown-hr-strings)))
2773 (insert (car markdown-hr-strings))))
2774 (markdown-ensure-blank-line-after))
2776 (defun markdown-insert-bold ()
2777 "Insert markup to make a region or word bold.
2778 If there is an active region, make the region bold. If the point
2779 is at a non-bold word, make the word bold. If the point is at a
2780 bold word or phrase, remove the bold markup. Otherwise, simply
2781 insert bold delimiters and place the cursor in between them."
2782 (interactive)
2783 (let ((delim (if markdown-bold-underscore "__" "**")))
2784 (if (markdown-use-region-p)
2785 ;; Active region
2786 (let ((bounds (markdown-unwrap-things-in-region
2787 (region-beginning) (region-end)
2788 markdown-regex-bold 2 4)))
2789 (markdown-wrap-or-insert delim delim nil (car bounds) (cdr bounds)))
2790 ;; Bold markup removal, bold word at point, or empty markup insertion
2791 (if (thing-at-point-looking-at markdown-regex-bold)
2792 (markdown-unwrap-thing-at-point nil 2 4)
2793 (markdown-wrap-or-insert delim delim 'word nil nil)))))
2795 (defun markdown-insert-italic ()
2796 "Insert markup to make a region or word italic.
2797 If there is an active region, make the region italic. If the point
2798 is at a non-italic word, make the word italic. If the point is at an
2799 italic word or phrase, remove the italic markup. Otherwise, simply
2800 insert italic delimiters and place the cursor in between them."
2801 (interactive)
2802 (let ((delim (if markdown-italic-underscore "_" "*")))
2803 (if (markdown-use-region-p)
2804 ;; Active region
2805 (let ((bounds (markdown-unwrap-things-in-region
2806 (region-beginning) (region-end)
2807 markdown-regex-italic 1 3)))
2808 (markdown-wrap-or-insert delim delim nil (car bounds) (cdr bounds)))
2809 ;; Italic markup removal, italic word at point, or empty markup insertion
2810 (if (thing-at-point-looking-at markdown-regex-italic)
2811 (markdown-unwrap-thing-at-point nil 1 3)
2812 (markdown-wrap-or-insert delim delim 'word nil nil)))))
2814 (defun markdown-insert-strike-through ()
2815 "Insert markup to make a region or word strikethrough.
2816 If there is an active region, make the region strikethrough. If the point
2817 is at a non-bold word, make the word strikethrough. If the point is at a
2818 strikethrough word or phrase, remove the strikethrough markup. Otherwise,
2819 simply insert bold delimiters and place the cursor in between them."
2820 (interactive)
2821 (let ((delim "~~"))
2822 (if (markdown-use-region-p)
2823 ;; Active region
2824 (let ((bounds (markdown-unwrap-things-in-region
2825 (region-beginning) (region-end)
2826 markdown-regex-strike-through 2 4)))
2827 (markdown-wrap-or-insert delim delim nil (car bounds) (cdr bounds)))
2828 ;; Strikethrough markup removal, strikethrough word at point, or empty markup insertion
2829 (if (thing-at-point-looking-at markdown-regex-strike-through)
2830 (markdown-unwrap-thing-at-point nil 2 4)
2831 (markdown-wrap-or-insert delim delim 'word nil nil)))))
2833 (defun markdown-insert-code ()
2834 "Insert markup to make a region or word an inline code fragment.
2835 If there is an active region, make the region an inline code
2836 fragment. If the point is at a word, make the word an inline
2837 code fragment. Otherwise, simply insert code delimiters and
2838 place the cursor in between them."
2839 (interactive)
2840 (if (markdown-use-region-p)
2841 ;; Active region
2842 (let ((bounds (markdown-unwrap-things-in-region
2843 (region-beginning) (region-end)
2844 markdown-regex-code 1 3)))
2845 (markdown-wrap-or-insert "`" "`" nil (car bounds) (cdr bounds)))
2846 ;; Code markup removal, code markup for word, or empty markup insertion
2847 (if (markdown-code-at-point-p)
2848 (markdown-unwrap-thing-at-point nil 0 2)
2849 (markdown-wrap-or-insert "`" "`" 'word nil nil))))
2851 (defun markdown-insert-kbd ()
2852 "Insert markup to wrap region or word in <kbd> tags.
2853 If there is an active region, use the region. If the point is at
2854 a word, use the word. Otherwise, simply insert <kbd> tags and
2855 place the cursor in between them."
2856 (interactive)
2857 (if (markdown-use-region-p)
2858 ;; Active region
2859 (let ((bounds (markdown-unwrap-things-in-region
2860 (region-beginning) (region-end)
2861 markdown-regex-kbd 0 2)))
2862 (markdown-wrap-or-insert "<kbd>" "</kbd>" nil (car bounds) (cdr bounds)))
2863 ;; Markup removal, markup for word, or empty markup insertion
2864 (if (thing-at-point-looking-at markdown-regex-kbd)
2865 (markdown-unwrap-thing-at-point nil 0 2)
2866 (markdown-wrap-or-insert "<kbd>" "</kbd>" 'word nil nil))))
2868 (defun markdown-insert-link ()
2869 "Insert an inline link, using region or word as link text if possible.
2870 If there is an active region, use the region as the link text. If the
2871 point is at a word, use the word as the link text. In these cases, the
2872 point will be left at the position for inserting a URL. If there is no
2873 active region and the point is not at word, simply insert link markup and
2874 place the point in the position to enter link text."
2875 (interactive)
2876 (let ((bounds (markdown-wrap-or-insert "[" "]()")))
2877 (when bounds
2878 (goto-char (- (cdr bounds) 1)))))
2880 (defun markdown-insert-reference-link (text label &optional url title)
2881 "Insert a reference link and, optionally, a reference definition.
2882 The link TEXT will be inserted followed by the optional LABEL.
2883 If a URL is given, also insert a definition for the reference
2884 LABEL according to `markdown-reference-location'. If a TITLE is
2885 given, it will be added to the end of the reference definition
2886 and will be used to populate the title attribute when converted
2887 to XHTML. If URL is nil, insert only the link portion (for
2888 example, when a reference label is already defined)."
2889 (insert (concat "[" text "][" label "]"))
2890 (when url
2891 (markdown-insert-reference-definition
2892 (if (string-equal label "") text label)
2893 url title)))
2895 (defun markdown-insert-reference-definition (label &optional url title)
2896 "Add definition for reference LABEL with URL and TITLE.
2897 LABEL is a Markdown reference label without square brackets.
2898 URL and TITLE are optional. When given, the TITLE will
2899 be used to populate the title attribute when converted to XHTML."
2900 ;; END specifies where to leave the point upon return
2901 (let ((end (point)))
2902 (cond
2903 ((eq markdown-reference-location 'end) (goto-char (point-max)))
2904 ((eq markdown-reference-location 'immediately) (markdown-end-of-block))
2905 ((eq markdown-reference-location 'header) (markdown-end-of-defun)))
2906 (unless (markdown-cur-line-blank-p) (insert "\n"))
2907 (insert "\n[" label "]: ")
2908 (if url
2909 (insert url)
2910 ;; When no URL is given, leave cursor at END following the colon
2911 (setq end (point)))
2912 (when title
2913 (insert " \"" title "\""))
2914 (unless (looking-at "\n")
2915 (insert "\n"))
2916 (goto-char end)
2917 (when url
2918 (message
2919 (substitute-command-keys
2920 "Defined reference [%s], press \\[markdown-jump] to jump there")
2921 label))))
2923 (defun markdown-insert-reference-link-dwim ()
2924 "Insert a reference link of the form [text][label] at point.
2925 If there is an active region, the text in the region will be used
2926 as the link text. If the point is at an inline link, it will be
2927 converted to a reference link. If the point is at a word, it will
2928 be used as the link text. Otherwise, the link text will be read from
2929 the minibuffer. The link label will be read from the minibuffer in
2930 both cases, with completion from the set of currently defined
2931 references. To create an implicit reference link, press RET to
2932 accept the default, an empty label. If the entered referenced
2933 label is not defined, additionally prompt for the URL
2934 and (optional) title. The reference definition is placed at the
2935 location determined by `markdown-reference-location'."
2936 (interactive)
2937 (let* ((defined-labels (mapcar (lambda (x) (substring x 1 -1))
2938 (markdown-get-defined-references)))
2939 (switch (thing-at-point-looking-at markdown-regex-link-inline))
2940 (bounds (cond ((markdown-use-region-p)
2941 (cons (region-beginning) (region-end)))
2942 (switch
2943 (cons (match-beginning 0) (match-end 0)))
2945 (markdown-bounds-of-thing-at-point 'word))))
2946 (text (cond (switch (match-string 3))
2947 (bounds (buffer-substring (car bounds) (cdr bounds)))
2948 (t (read-string "Link Text: "))))
2949 (label (completing-read
2950 "Link Label (default: none): " defined-labels
2951 nil nil nil 'markdown-reference-label-history nil))
2952 (ref (save-match-data
2953 (markdown-reference-definition
2954 (if (> (length label) 0) label text))))
2955 (url (cond (ref nil)
2956 (switch (match-string 6))
2957 (t (read-string "Link URL: "))))
2958 (title (cond
2959 ((= (length url) 0) nil)
2960 (switch (if (> (length (match-string 7)) 2)
2961 (substring (match-string 7) 1 -1)
2962 nil))
2963 (t (read-string "Link Title (optional): ")))))
2964 (when bounds (delete-region (car bounds) (cdr bounds)))
2965 (markdown-insert-reference-link text label url title)))
2967 (defun markdown-insert-uri ()
2968 "Insert markup for an inline URI.
2969 If there is an active region, use it as the URI. If the point is
2970 at a URI, wrap it with angle brackets. If the point is at an
2971 inline URI, remove the angle brackets. Otherwise, simply insert
2972 angle brackets place the point between them."
2973 (interactive)
2974 (if (markdown-use-region-p)
2975 ;; Active region
2976 (let ((bounds (markdown-unwrap-things-in-region
2977 (region-beginning) (region-end)
2978 markdown-regex-angle-uri 0 2)))
2979 (markdown-wrap-or-insert "<" ">" nil (car bounds) (cdr bounds)))
2980 ;; Markup removal, URI at point, or empty markup insertion
2981 (if (thing-at-point-looking-at markdown-regex-angle-uri)
2982 (markdown-unwrap-thing-at-point nil 0 2)
2983 (markdown-wrap-or-insert "<" ">" 'url nil nil))))
2985 (defun markdown-insert-wiki-link ()
2986 "Insert a wiki link of the form [[WikiLink]].
2987 If there is an active region, use the region as the link text.
2988 If the point is at a word, use the word as the link text. If
2989 there is no active region and the point is not at word, simply
2990 insert link markup."
2991 (interactive)
2992 (if (markdown-use-region-p)
2993 ;; Active region
2994 (markdown-wrap-or-insert "[[" "]]" nil (region-beginning) (region-end))
2995 ;; Markup removal, wiki link at at point, or empty markup insertion
2996 (if (thing-at-point-looking-at markdown-regex-wiki-link)
2997 (if (or markdown-wiki-link-alias-first
2998 (null (match-string 5)))
2999 (markdown-unwrap-thing-at-point nil 1 3)
3000 (markdown-unwrap-thing-at-point nil 1 5))
3001 (markdown-wrap-or-insert "[[" "]]"))))
3003 (defun markdown-insert-image (&optional arg)
3004 "Insert image markup using region or word as alt text if possible.
3005 If there is an active region, use the region as the alt text. If the
3006 point is at a word, use the word as the alt text. In these cases, the
3007 point will be left at the position for inserting a URL. If there is no
3008 active region and the point is not at word, simply insert image markup and
3009 place the point in the position to enter alt text. If ARG is nil, insert
3010 inline image markup. Otherwise, insert reference image markup."
3011 (interactive "*P")
3012 (let ((bounds (if arg
3013 (markdown-wrap-or-insert "![" "][]")
3014 (markdown-wrap-or-insert "![" "]()"))))
3015 (when bounds
3016 (goto-char (- (cdr bounds) 1)))))
3018 (defun markdown-insert-reference-image ()
3019 "Insert reference-style image markup using region or word as alt text.
3020 Calls `markdown-insert-image' with prefix argument."
3021 (interactive)
3022 (markdown-insert-image t))
3024 (defun markdown-remove-header ()
3025 "Remove header markup if point is at a header.
3026 Return bounds of remaining header text if a header was removed
3027 and nil otherwise."
3028 (interactive "*")
3029 (or (markdown-unwrap-thing-at-point markdown-regex-header-atx 0 2)
3030 (markdown-unwrap-thing-at-point markdown-regex-header-setext 0 1)))
3032 (defun markdown-insert-header (&optional level text setext)
3033 "Insert or replace header markup.
3034 The level of the header is specified by LEVEL and header text is
3035 given by TEXT. LEVEL must be an integer from 1 and 6, and the
3036 default value is 1.
3037 When TEXT is nil, the header text is obtained as follows.
3038 If there is an active region, it is used as the header text.
3039 Otherwise, the current line will be used as the header text.
3040 If there is not an active region and the point is at a header,
3041 remove the header markup and replace with level N header.
3042 Otherwise, insert empty header markup and place the cursor in
3043 between.
3044 The style of the header will be atx (hash marks) unless
3045 SETEXT is non-nil, in which case a setext-style (underlined)
3046 header will be inserted."
3047 (interactive "p\nsHeader text: ")
3048 (setq level (min (max (or level 1) 1) (if setext 2 6)))
3049 ;; Determine header text if not given
3050 (when (null text)
3051 (if (markdown-use-region-p)
3052 ;; Active region
3053 (setq text (delete-and-extract-region (region-beginning) (region-end)))
3054 ;; No active region
3055 (markdown-remove-header)
3056 (setq text (delete-and-extract-region
3057 (line-beginning-position) (line-end-position)))
3058 (when (and setext (string-match "^[ \t]*$" text))
3059 (setq text (read-string "Header text: "))))
3060 (setq text (markdown-compress-whitespace-string text)))
3061 ;; Insertion with given text
3062 (markdown-ensure-blank-line-before)
3063 (let (hdr)
3064 (cond (setext
3065 (setq hdr (make-string (string-width text) (if (= level 2) ?- ?=)))
3066 (insert text "\n" hdr))
3068 (setq hdr (make-string level ?#))
3069 (insert hdr " " text)
3070 (when (null markdown-asymmetric-header) (insert " " hdr)))))
3071 (markdown-ensure-blank-line-after)
3072 ;; Leave point at end of text
3073 (if setext
3074 (backward-char (1+ (string-width text)))
3075 (backward-char (1+ level))))
3077 (defun markdown-insert-header-dwim (&optional arg setext)
3078 "Insert or replace header markup.
3079 The level and type of the header are determined automatically by
3080 the type and level of the previous header, unless a prefix
3081 argument is given via ARG.
3082 With a numeric prefix valued 1 to 6, insert a header of the given
3083 level, with the type being determined automatically (note that
3084 only level 1 or 2 setext headers are possible).
3086 With a \\[universal-argument] prefix (i.e., when ARG is (4)),
3087 promote the heading by one level.
3088 With two \\[universal-argument] prefixes (i.e., when ARG is (16)),
3089 demote the heading by one level.
3090 When SETEXT is non-nil, prefer setext-style headers when
3091 possible (levels one and two).
3093 When there is an active region, use it for the header text. When
3094 the point is at an existing header, change the type and level
3095 according to the rules above.
3096 Otherwise, if the line is not empty, create a header using the
3097 text on the current line as the header text.
3098 Finally, if the point is on a blank line, insert empty header
3099 markup (atx) or prompt for text (setext).
3100 See `markdown-insert-header' for more details about how the
3101 header text is determined."
3102 (interactive "*P")
3103 (let (level)
3104 (save-excursion
3105 (when (or (thing-at-point-looking-at markdown-regex-header)
3106 (re-search-backward markdown-regex-header nil t))
3107 ;; level of current or previous header
3108 (setq level (markdown-outline-level))
3109 ;; match groups 1 and 3 indicate setext headers
3110 (setq setext (or setext (match-end 1) (match-end 3)))))
3111 ;; check prefix argument
3112 (cond
3113 ((and (equal arg '(4)) level (> level 1)) ;; C-u
3114 (cl-decf level))
3115 ((and (equal arg '(16)) level (< level 6)) ;; C-u C-u
3116 (cl-incf level))
3117 (arg ;; numeric prefix
3118 (setq level (prefix-numeric-value arg))))
3119 ;; setext headers must be level one or two
3120 (and level (setq setext (and setext (<= level 2))))
3121 ;; insert the heading
3122 (markdown-insert-header level nil setext)))
3124 (defun markdown-insert-header-setext-dwim (&optional arg)
3125 "Insert or replace header markup, with preference for setext.
3126 See `markdown-insert-header-dwim' for details, including how ARG is handled."
3127 (interactive "*P")
3128 (markdown-insert-header-dwim arg t))
3130 (defun markdown-insert-header-atx-1 ()
3131 "Insert a first level atx-style (hash mark) header.
3132 See `markdown-insert-header'."
3133 (interactive "*")
3134 (markdown-insert-header 1 nil nil))
3136 (defun markdown-insert-header-atx-2 ()
3137 "Insert a level two atx-style (hash mark) header.
3138 See `markdown-insert-header'."
3139 (interactive "*")
3140 (markdown-insert-header 2 nil nil))
3142 (defun markdown-insert-header-atx-3 ()
3143 "Insert a level three atx-style (hash mark) header.
3144 See `markdown-insert-header'."
3145 (interactive "*")
3146 (markdown-insert-header 3 nil nil))
3148 (defun markdown-insert-header-atx-4 ()
3149 "Insert a level four atx-style (hash mark) header.
3150 See `markdown-insert-header'."
3151 (interactive "*")
3152 (markdown-insert-header 4 nil nil))
3154 (defun markdown-insert-header-atx-5 ()
3155 "Insert a level five atx-style (hash mark) header.
3156 See `markdown-insert-header'."
3157 (interactive "*")
3158 (markdown-insert-header 5 nil nil))
3160 (defun markdown-insert-header-atx-6 ()
3161 "Insert a sixth level atx-style (hash mark) header.
3162 See `markdown-insert-header'."
3163 (interactive "*")
3164 (markdown-insert-header 6 nil nil))
3166 (defun markdown-insert-header-setext-1 ()
3167 "Insert a setext-style (underlined) first-level header.
3168 See `markdown-insert-header'."
3169 (interactive "*")
3170 (markdown-insert-header 1 nil t))
3172 (defun markdown-insert-header-setext-2 ()
3173 "Insert a setext-style (underlined) second-level header.
3174 See `markdown-insert-header'."
3175 (interactive "*")
3176 (markdown-insert-header 2 nil t))
3178 (defun markdown-blockquote-indentation (loc)
3179 "Return string containing necessary indentation for a blockquote at LOC.
3180 Also see `markdown-pre-indentation'."
3181 (save-excursion
3182 (goto-char loc)
3183 (let* ((list-level (length (markdown-calculate-list-levels)))
3184 (indent ""))
3185 (dotimes (count list-level indent)
3186 (setq indent (concat indent " "))))))
3188 (defun markdown-insert-blockquote ()
3189 "Start a blockquote section (or blockquote the region).
3190 If Transient Mark mode is on and a region is active, it is used as
3191 the blockquote text."
3192 (interactive)
3193 (if (markdown-use-region-p)
3194 (markdown-blockquote-region (region-beginning) (region-end))
3195 (markdown-ensure-blank-line-before)
3196 (insert (markdown-blockquote-indentation (point)) "> ")
3197 (markdown-ensure-blank-line-after)))
3199 (defun markdown-block-region (beg end prefix)
3200 "Format the region using a block prefix.
3201 Arguments BEG and END specify the beginning and end of the
3202 region. The characters PREFIX will appear at the beginning
3203 of each line."
3204 (save-excursion
3205 (let* ((end-marker (make-marker))
3206 (beg-marker (make-marker)))
3207 ;; Ensure blank line after and remove extra whitespace
3208 (goto-char end)
3209 (skip-syntax-backward "-")
3210 (set-marker end-marker (point))
3211 (delete-horizontal-space)
3212 (markdown-ensure-blank-line-after)
3213 ;; Ensure blank line before and remove extra whitespace
3214 (goto-char beg)
3215 (skip-syntax-forward "-")
3216 (delete-horizontal-space)
3217 (markdown-ensure-blank-line-before)
3218 (set-marker beg-marker (point))
3219 ;; Insert PREFIX before each line
3220 (goto-char beg-marker)
3221 (while (and (< (line-beginning-position) end-marker)
3222 (not (eobp)))
3223 (insert prefix)
3224 (forward-line)))))
3226 (defun markdown-blockquote-region (beg end)
3227 "Blockquote the region.
3228 Arguments BEG and END specify the beginning and end of the region."
3229 (interactive "*r")
3230 (markdown-block-region
3231 beg end (concat (markdown-blockquote-indentation
3232 (max (point-min) (1- beg))) "> ")))
3234 (defun markdown-pre-indentation (loc)
3235 "Return string containing necessary whitespace for a pre block at LOC.
3236 Also see `markdown-blockquote-indentation'."
3237 (save-excursion
3238 (goto-char loc)
3239 (let* ((list-level (length (markdown-calculate-list-levels)))
3240 indent)
3241 (dotimes (count (1+ list-level) indent)
3242 (setq indent (concat indent " "))))))
3244 (defun markdown-insert-pre ()
3245 "Start a preformatted section (or apply to the region).
3246 If Transient Mark mode is on and a region is active, it is marked
3247 as preformatted text."
3248 (interactive)
3249 (if (markdown-use-region-p)
3250 (markdown-pre-region (region-beginning) (region-end))
3251 (markdown-ensure-blank-line-before)
3252 (insert (markdown-pre-indentation (point)))
3253 (markdown-ensure-blank-line-after)))
3255 (defun markdown-pre-region (beg end)
3256 "Format the region as preformatted text.
3257 Arguments BEG and END specify the beginning and end of the region."
3258 (interactive "*r")
3259 (let ((indent (markdown-pre-indentation (max (point-min) (1- beg)))))
3260 (markdown-block-region beg end indent)))
3262 (defun markdown-electric-backquote (arg)
3263 "Insert a backquote.
3264 The numeric prefix argument ARG says how many times to repeat the insertion.
3265 Call `markdown-insert-gfm-code-block' interactively
3266 if three backquotes inserted at the beginning of line."
3267 (interactive "*P")
3268 (self-insert-command (prefix-numeric-value arg))
3269 (when (and markdown-gfm-use-electric-backquote (looking-back "^```" nil))
3270 (replace-match "")
3271 (call-interactively #'markdown-insert-gfm-code-block)))
3273 (defconst markdown-gfm-recognized-languages
3274 ;; to reproduce/update, evaluate the let-form in
3275 ;; scripts/get-recognized-gfm-languages.el. that produces a single long sexp,
3276 ;; but with appropriate use of a keyboard macro, indenting and filling it
3277 ;; properly is pretty fast.
3278 '("ABAP" "AGS-Script" "AMPL" "ANTLR" "API-Blueprint" "APL" "ASP" "ATS"
3279 "ActionScript" "Ada" "Agda" "Alloy" "Ant-Build-System" "ApacheConf" "Apex"
3280 "AppleScript" "Arc" "Arduino" "AsciiDoc" "AspectJ" "Assembly" "Augeas"
3281 "AutoHotkey" "AutoIt" "Awk" "Batchfile" "Befunge" "Bison" "BitBake"
3282 "BlitzBasic" "BlitzMax" "Bluespec" "Boo" "Brainfuck" "Brightscript" "Bro" "C#"
3283 "C++" "C-ObjDump" "C2hs-Haskell" "CLIPS" "CMake" "COBOL" "CSS" "Cap'n-Proto"
3284 "CartoCSS" "Ceylon" "Chapel" "Charity" "ChucK" "Cirru" "Clarion" "Clean"
3285 "Click" "Clojure" "CoffeeScript" "ColdFusion" "ColdFusion-CFC" "Common-Lisp"
3286 "Component-Pascal" "Cool" "Coq" "Cpp-ObjDump" "Creole" "Crystal" "Cucumber"
3287 "Cuda" "Cycript" "Cython" "D-ObjDump" "DIGITAL-Command-Language" "DM"
3288 "DNS-Zone" "DTrace" "Darcs-Patch" "Dart" "Diff" "Dockerfile" "Dogescript"
3289 "Dylan" "ECL" "ECLiPSe" "Eagle" "Ecere-Projects" "Eiffel" "Elixir" "Elm"
3290 "Emacs-Lisp" "EmberScript" "Erlang" "F#" "FLUX" "FORTRAN" "Factor" "Fancy"
3291 "Fantom" "Filterscript" "Formatted" "Forth" "FreeMarker" "Frege" "G-code"
3292 "GAMS" "GAP" "GAS" "GDScript" "GLSL" "Game-Maker-Language" "Genshi"
3293 "Gentoo-Ebuild" "Gentoo-Eclass" "Gettext-Catalog" "Glyph" "Gnuplot" "Go"
3294 "Golo" "Gosu" "Grace" "Gradle" "Grammatical-Framework"
3295 "Graph-Modeling-Language" "Graphviz-(DOT)" "Groff" "Groovy"
3296 "Groovy-Server-Pages" "HCL" "HTML" "HTML+Django" "HTML+EEX" "HTML+ERB"
3297 "HTML+PHP" "HTTP" "Hack" "Haml" "Handlebars" "Harbour" "Haskell" "Haxe" "Hy"
3298 "HyPhy" "IDL" "IGOR-Pro" "INI" "IRC-log" "Idris" "Inform-7" "Inno-Setup" "Io"
3299 "Ioke" "Isabelle" "Isabelle-ROOT" "JFlex" "JSON" "JSON5" "JSONLD" "JSONiq"
3300 "JSX" "Jade" "Jasmin" "Java" "Java-Server-Pages" "JavaScript" "Julia"
3301 "Jupyter-Notebook" "KRL" "KiCad" "Kit" "Kotlin" "LFE" "LLVM" "LOLCODE" "LSL"
3302 "LabVIEW" "Lasso" "Latte" "Lean" "Less" "Lex" "LilyPond" "Limbo"
3303 "Linker-Script" "Linux-Kernel-Module" "Liquid" "Literate-Agda"
3304 "Literate-CoffeeScript" "Literate-Haskell" "LiveScript" "Logos" "Logtalk"
3305 "LookML" "LoomScript" "Lua" "MAXScript" "MTML" "MUF" "Makefile" "Mako"
3306 "Markdown" "Mask" "Mathematica" "Matlab" "Maven-POM" "Max" "MediaWiki"
3307 "Mercury" "Metal" "MiniD" "Mirah" "Modelica" "Modula-2"
3308 "Module-Management-System" "Monkey" "Moocode" "MoonScript" "Myghty" "NCL" "NL"
3309 "NSIS" "Nemerle" "NetLinx" "NetLinx+ERB" "NetLogo" "NewLisp" "Nginx" "Nimrod"
3310 "Ninja" "Nit" "Nix" "Nu" "NumPy" "OCaml" "ObjDump" "Objective-C"
3311 "Objective-C++" "Objective-J" "Omgrofl" "Opa" "Opal" "OpenCL" "OpenEdge-ABL"
3312 "OpenSCAD" "Org" "Ox" "Oxygene" "Oz" "PAWN" "PHP" "PLSQL" "PLpgSQL" "Pan"
3313 "Papyrus" "Parrot" "Parrot-Assembly" "Parrot-Internal-Representation" "Pascal"
3314 "Perl" "Perl6" "Pickle" "PicoLisp" "PigLatin" "Pike" "Pod" "PogoScript" "Pony"
3315 "PostScript" "PowerShell" "Processing" "Prolog" "Propeller-Spin"
3316 "Protocol-Buffer" "Public-Key" "Puppet" "Pure-Data" "PureBasic" "PureScript"
3317 "Python" "Python-traceback" "QML" "QMake" "RAML" "RDoc" "REALbasic" "RHTML"
3318 "RMarkdown" "Racket" "Ragel-in-Ruby-Host" "Raw-token-data" "Rebol" "Red"
3319 "Redcode" "Ren'Py" "RenderScript" "RobotFramework" "Rouge" "Ruby" "Rust" "SAS"
3320 "SCSS" "SMT" "SPARQL" "SQF" "SQL" "SQLPL" "STON" "SVG" "Sage" "SaltStack"
3321 "Sass" "Scala" "Scaml" "Scheme" "Scilab" "Self" "Shell" "ShellSession" "Shen"
3322 "Slash" "Slim" "Smali" "Smalltalk" "Smarty" "SourcePawn" "Squirrel" "Stan"
3323 "Standard-ML" "Stata" "Stylus" "SuperCollider" "Swift" "SystemVerilog" "TOML"
3324 "TXL" "Tcl" "Tcsh" "TeX" "Tea" "Text" "Textile" "Thrift" "Turing" "Turtle"
3325 "Twig" "TypeScript" "Unified-Parallel-C" "Unity3D-Asset" "UnrealScript"
3326 "UrWeb" "VCL" "VHDL" "Vala" "Verilog" "VimL" "Visual-Basic" "Volt" "Vue"
3327 "Web-Ontology-Language" "WebIDL" "X10" "XC" "XML" "XPages" "XProc" "XQuery"
3328 "XS" "XSLT" "Xojo" "Xtend" "YAML" "Yacc" "Zephir" "Zimpl" "desktop" "eC" "edn"
3329 "fish" "mupad" "nesC" "ooc" "reStructuredText" "wisp" "xBase")
3330 "Language specifiers recognized by github's syntax highlighting features.")
3332 (defvar markdown-gfm-used-languages nil
3333 "Languages used in the current buffer in GFM code blocks, which are not
3334 already in `markdown-gfm-recognized-languages' or
3335 `markdown-gfm-additional-languages'.")
3336 (make-variable-buffer-local 'markdown-gfm-used-languages)
3337 (defvar markdown-gfm-last-used-language nil
3338 "Last language used in the current buffer in GFM code blocks.")
3339 (make-variable-buffer-local 'markdown-gfm-last-used-language)
3341 (defun markdown-trim-whitespace (str)
3342 (markdown-replace-regexp-in-string
3343 "\\(?:[[:space:]\r\n]+\\'\\|\\`[[:space:]\r\n]+\\)" "" str))
3345 (defun markdown-clean-language-string (str)
3346 (markdown-replace-regexp-in-string
3347 "{\\.?\\|}" "" (markdown-trim-whitespace str)))
3349 (defun markdown-validate-language-string (widget)
3350 (let ((str (widget-value widget)))
3351 (unless (string= str (markdown-clean-language-string str))
3352 (widget-put widget :error (format "Invalid language spec: '%s'" str))
3353 widget)))
3355 (defun markdown-gfm-get-corpus ()
3356 "Create corpus of recognized GFM code block languages for the given buffer."
3357 (let ((given-corpus (append markdown-gfm-additional-languages
3358 markdown-gfm-recognized-languages)))
3359 (append
3360 markdown-gfm-used-languages
3361 (if markdown-gfm-downcase-languages (cl-mapcar #'downcase given-corpus)
3362 given-corpus))))
3364 (defun markdown-add-language-if-new (lang)
3365 (let* ((cleaned-lang (markdown-clean-language-string lang))
3366 (find-result
3367 (cl-find cleaned-lang (markdown-gfm-get-corpus)
3368 :test #'equal)))
3369 (setq markdown-gfm-last-used-language cleaned-lang)
3370 (unless find-result (push cleaned-lang markdown-gfm-used-languages))))
3372 (defun markdown-insert-gfm-code-block (&optional lang)
3373 "Insert GFM code block for language LANG.
3374 If LANG is nil, the language will be queried from user. If a
3375 region is active, wrap this region with the markup instead. If
3376 the region boundaries are not on empty lines, these are added
3377 automatically in order to have the correct markup."
3378 (interactive
3379 (list (let ((completion-ignore-case nil))
3380 (condition-case nil
3381 (markdown-clean-language-string
3382 (completing-read
3383 (format "Programming language [%s]: "
3384 (or markdown-gfm-last-used-language "none"))
3385 (markdown-gfm-get-corpus)
3386 nil 'confirm nil
3387 'markdown-gfm-language-history))
3388 (quit "")))))
3389 (unless (string= lang "") (markdown-add-language-if-new lang))
3390 (when (> (length lang) 0) (setq lang (concat " " lang)))
3391 (if (markdown-use-region-p)
3392 (let ((b (region-beginning)) (e (region-end)))
3393 (goto-char e)
3394 ;; if we're on a blank line, don't newline, otherwise the ```
3395 ;; should go on its own line
3396 (unless (looking-back "\n" nil)
3397 (newline))
3398 (insert "```")
3399 (markdown-ensure-blank-line-after)
3400 (goto-char b)
3401 ;; if we're on a blank line, insert the quotes here, otherwise
3402 ;; add a new line first
3403 (unless (looking-at "\n")
3404 (newline)
3405 (forward-line -1))
3406 (markdown-ensure-blank-line-before)
3407 (insert "```" lang))
3408 (markdown-ensure-blank-line-before)
3409 (insert "```" lang "\n\n```")
3410 (markdown-ensure-blank-line-after)
3411 (forward-line -1)))
3413 (defun markdown-gfm-parse-buffer-for-languages (&optional buffer)
3414 (with-current-buffer (or buffer (current-buffer))
3415 (save-excursion
3416 (goto-char (point-min))
3417 (while (re-search-forward markdown-regex-gfm-code-block-open nil t)
3418 (let ((lang (match-string-no-properties 2)))
3419 (when lang (markdown-add-language-if-new lang)))))))
3422 ;;; Footnotes ======================================================================
3424 (defun markdown-footnote-counter-inc ()
3425 "Increment `markdown-footnote-counter' and return the new value."
3426 (when (= markdown-footnote-counter 0) ; hasn't been updated in this buffer yet.
3427 (save-excursion
3428 (goto-char (point-min))
3429 (while (re-search-forward (concat "^\\[\\^\\(" markdown-footnote-chars "*?\\)\\]:")
3430 (point-max) t)
3431 (let ((fn (string-to-number (match-string 1))))
3432 (when (> fn markdown-footnote-counter)
3433 (setq markdown-footnote-counter fn))))))
3434 (cl-incf markdown-footnote-counter))
3436 (defun markdown-insert-footnote ()
3437 "Insert footnote with a new number and move point to footnote definition."
3438 (interactive)
3439 (let ((fn (markdown-footnote-counter-inc)))
3440 (insert (format "[^%d]" fn))
3441 (markdown-footnote-text-find-new-location)
3442 (markdown-ensure-blank-line-before)
3443 (unless (markdown-cur-line-blank-p)
3444 (insert "\n"))
3445 (insert (format "[^%d]: " fn))
3446 (markdown-ensure-blank-line-after)))
3448 (defun markdown-footnote-text-find-new-location ()
3449 "Position the cursor at the proper location for a new footnote text."
3450 (cond
3451 ((eq markdown-footnote-location 'end) (goto-char (point-max)))
3452 ((eq markdown-footnote-location 'immediately) (markdown-end-of-block))
3453 ((eq markdown-footnote-location 'header) (markdown-end-of-defun))))
3455 (defun markdown-footnote-kill ()
3456 "Kill the footnote at point.
3457 The footnote text is killed (and added to the kill ring), the
3458 footnote marker is deleted. Point has to be either at the
3459 footnote marker or in the footnote text."
3460 (interactive)
3461 (let ((marker-pos nil)
3462 (skip-deleting-marker nil)
3463 (starting-footnote-text-positions
3464 (markdown-footnote-text-positions)))
3465 (when starting-footnote-text-positions
3466 ;; We're starting in footnote text, so mark our return position and jump
3467 ;; to the marker if possible.
3468 (let ((marker-pos (markdown-footnote-find-marker
3469 (cl-first starting-footnote-text-positions))))
3470 (if marker-pos
3471 (goto-char (1- marker-pos))
3472 ;; If there isn't a marker, we still want to kill the text.
3473 (setq skip-deleting-marker t))))
3474 ;; Either we didn't start in the text, or we started in the text and jumped
3475 ;; to the marker. We want to assume we're at the marker now and error if
3476 ;; we're not.
3477 (unless skip-deleting-marker
3478 (let ((marker (markdown-footnote-delete-marker)))
3479 (unless marker
3480 (error "Not at a footnote"))
3481 ;; Even if we knew the text position before, it changed when we deleted
3482 ;; the label.
3483 (setq marker-pos (cl-second marker))
3484 (let ((new-text-pos (markdown-footnote-find-text (cl-first marker))))
3485 (unless new-text-pos
3486 (error "No text for footnote `%s'" (cl-first marker)))
3487 (goto-char new-text-pos))))
3488 (let ((pos (markdown-footnote-kill-text)))
3489 (goto-char (if starting-footnote-text-positions
3491 marker-pos)))))
3493 (defun markdown-footnote-delete-marker ()
3494 "Delete a footnote marker at point.
3495 Returns a list (ID START) containing the footnote ID and the
3496 start position of the marker before deletion. If no footnote
3497 marker was deleted, this function returns NIL."
3498 (let ((marker (markdown-footnote-marker-positions)))
3499 (when marker
3500 (delete-region (cl-second marker) (cl-third marker))
3501 (butlast marker))))
3503 (defun markdown-footnote-kill-text ()
3504 "Kill footnote text at point.
3505 Returns the start position of the footnote text before deletion,
3506 or NIL if point was not inside a footnote text.
3508 The killed text is placed in the kill ring (without the footnote
3509 number)."
3510 (let ((fn (markdown-footnote-text-positions)))
3511 (when fn
3512 (let ((text (delete-and-extract-region (cl-second fn) (cl-third fn))))
3513 (string-match (concat "\\[\\" (cl-first fn) "\\]:[[:space:]]*\\(\\(.*\n?\\)*\\)") text)
3514 (kill-new (match-string 1 text))
3515 (when (and (markdown-cur-line-blank-p)
3516 (markdown-prev-line-blank-p)
3517 (not (bobp)))
3518 (delete-region (1- (point)) (point)))
3519 (cl-second fn)))))
3521 (defun markdown-footnote-goto-text ()
3522 "Jump to the text of the footnote at point."
3523 (interactive)
3524 (let ((fn (car (markdown-footnote-marker-positions))))
3525 (unless fn
3526 (error "Not at a footnote marker"))
3527 (let ((new-pos (markdown-footnote-find-text fn)))
3528 (unless new-pos
3529 (error "No definition found for footnote `%s'" fn))
3530 (goto-char new-pos))))
3532 (defun markdown-footnote-return ()
3533 "Return from a footnote to its footnote number in the main text."
3534 (interactive)
3535 (let ((fn (save-excursion
3536 (car (markdown-footnote-text-positions)))))
3537 (unless fn
3538 (error "Not in a footnote"))
3539 (let ((new-pos (markdown-footnote-find-marker fn)))
3540 (unless new-pos
3541 (error "Footnote marker `%s' not found" fn))
3542 (goto-char new-pos))))
3544 (defun markdown-footnote-find-marker (id)
3545 "Find the location of the footnote marker with ID.
3546 The actual buffer position returned is the position directly
3547 following the marker's closing bracket. If no marker is found,
3548 NIL is returned."
3549 (save-excursion
3550 (goto-char (point-min))
3551 (when (re-search-forward (concat "\\[" id "\\]\\([^:]\\|\\'\\)") nil t)
3552 (skip-chars-backward "^]")
3553 (point))))
3555 (defun markdown-footnote-find-text (id)
3556 "Find the location of the text of footnote ID.
3557 The actual buffer position returned is the position of the first
3558 character of the text, after the footnote's identifier. If no
3559 footnote text is found, NIL is returned."
3560 (save-excursion
3561 (goto-char (point-min))
3562 (when (re-search-forward (concat "^\\[" id "\\]:") nil t)
3563 (skip-chars-forward "[ \t]")
3564 (point))))
3566 (defun markdown-footnote-marker-positions ()
3567 "Return the position and ID of the footnote marker point is on.
3568 The return value is a list (ID START END). If point is not on a
3569 footnote, NIL is returned."
3570 ;; first make sure we're at a footnote marker
3571 (if (or (looking-back (concat "\\[\\^" markdown-footnote-chars "*\\]?") (line-beginning-position))
3572 (looking-at (concat "\\[?\\^" markdown-footnote-chars "*?\\]")))
3573 (save-excursion
3574 ;; move point between [ and ^:
3575 (if (looking-at "\\[")
3576 (forward-char 1)
3577 (skip-chars-backward "^["))
3578 (looking-at (concat "\\(\\^" markdown-footnote-chars "*?\\)\\]"))
3579 (list (match-string 1) (1- (match-beginning 1)) (1+ (match-end 1))))))
3581 (defun markdown-footnote-text-positions ()
3582 "Return the start and end positions of the footnote text point is in.
3583 The exact return value is a list of three elements: (ID START END).
3584 The start position is the position of the opening bracket
3585 of the footnote id. The end position is directly after the
3586 newline that ends the footnote. If point is not in a footnote,
3587 NIL is returned instead."
3588 (save-excursion
3589 (let (result)
3590 (move-beginning-of-line 1)
3591 ;; Try to find the label. If we haven't found the label and we're at a blank
3592 ;; or indented line, back up if possible.
3593 (while (and
3594 (not (and (looking-at markdown-regex-footnote-definition)
3595 (setq result (list (match-string 1) (point)))))
3596 (and (not (bobp))
3597 (or (markdown-cur-line-blank-p)
3598 (>= (markdown-cur-line-indent) 4))))
3599 (forward-line -1))
3600 (when result
3601 ; Advance if there is a next line that is either blank or indented.
3602 ; (Need to check if we're on the last line, because
3603 ; markdown-next-line-blank-p returns true for last line in buffer.)
3604 (while (and (/= (line-end-position) (point-max))
3605 (or (markdown-next-line-blank-p)
3606 (>= (markdown-next-line-indent) 4)))
3607 (forward-line))
3608 ; Move back while the current line is blank.
3609 (while (markdown-cur-line-blank-p)
3610 (forward-line -1))
3611 ; Advance to capture this line and a single trailing newline (if there
3612 ; is one).
3613 (forward-line)
3614 (append result (list (point)))))))
3617 ;;; Element Removal ===========================================================
3619 (defun markdown-kill-thing-at-point ()
3620 "Kill thing at point and add important text, without markup, to kill ring.
3621 Possible things to kill include (roughly in order of precedence):
3622 inline code, headers, horizonal rules, links (add link text to
3623 kill ring), images (add alt text to kill ring), angle uri, email
3624 addresses, bold, italics, reference definition (add URI to kill
3625 ring), footnote markers and text (kill both marker and text, add
3626 text to kill ring), and list items."
3627 (interactive "*")
3628 (let (val tmp)
3629 (cond
3630 ;; Inline code
3631 ((markdown-code-at-point-p)
3632 (kill-new (match-string 2))
3633 (delete-region (match-beginning 0) (match-end 0)))
3634 ;; ATX header
3635 ((thing-at-point-looking-at markdown-regex-header-atx)
3636 (kill-new (match-string 2))
3637 (delete-region (match-beginning 0) (match-end 0)))
3638 ;; Setext header
3639 ((thing-at-point-looking-at markdown-regex-header-setext)
3640 (kill-new (match-string 1))
3641 (delete-region (match-beginning 0) (match-end 0)))
3642 ;; Horizonal rule
3643 ((thing-at-point-looking-at markdown-regex-hr)
3644 (kill-new (match-string 0))
3645 (delete-region (match-beginning 0) (match-end 0)))
3646 ;; Inline link or image (add link or alt text to kill ring)
3647 ((thing-at-point-looking-at markdown-regex-link-inline)
3648 (kill-new (match-string 3))
3649 (delete-region (match-beginning 0) (match-end 0)))
3650 ;; Reference link or image (add link or alt text to kill ring)
3651 ((thing-at-point-looking-at markdown-regex-link-reference)
3652 (kill-new (match-string 3))
3653 (delete-region (match-beginning 0) (match-end 0)))
3654 ;; Angle URI (add URL to kill ring)
3655 ((thing-at-point-looking-at markdown-regex-angle-uri)
3656 (kill-new (match-string 2))
3657 (delete-region (match-beginning 0) (match-end 0)))
3658 ;; Email address in angle brackets (add email address to kill ring)
3659 ((thing-at-point-looking-at markdown-regex-email)
3660 (kill-new (match-string 1))
3661 (delete-region (match-beginning 0) (match-end 0)))
3662 ;; Wiki link (add alias text to kill ring)
3663 ((thing-at-point-looking-at markdown-regex-wiki-link)
3664 (kill-new (markdown-wiki-link-alias))
3665 (delete-region (match-beginning 1) (match-end 1)))
3666 ;; Bold
3667 ((thing-at-point-looking-at markdown-regex-bold)
3668 (kill-new (match-string 4))
3669 (delete-region (match-beginning 2) (match-end 2)))
3670 ;; Italics
3671 ((thing-at-point-looking-at markdown-regex-italic)
3672 (kill-new (match-string 3))
3673 (delete-region (match-beginning 1) (match-end 1)))
3674 ;; Strikethrough
3675 ((thing-at-point-looking-at markdown-regex-strike-through)
3676 (kill-new (match-string 4))
3677 (delete-region (match-beginning 2) (match-end 2)))
3678 ;; Footnote marker (add footnote text to kill ring)
3679 ((thing-at-point-looking-at markdown-regex-footnote)
3680 (markdown-footnote-kill))
3681 ;; Footnote text (add footnote text to kill ring)
3682 ((setq val (markdown-footnote-text-positions))
3683 (markdown-footnote-kill))
3684 ;; Reference definition (add URL to kill ring)
3685 ((thing-at-point-looking-at markdown-regex-reference-definition)
3686 (kill-new (match-string 5))
3687 (delete-region (match-beginning 0) (match-end 0)))
3688 ;; List item
3689 ((setq val (markdown-cur-list-item-bounds))
3690 (kill-new (delete-and-extract-region (cl-first val) (cl-second val))))
3692 (error "Nothing found at point to kill")))))
3695 ;;; Indentation ====================================================================
3697 (defun markdown-indent-find-next-position (cur-pos positions)
3698 "Return the position after the index of CUR-POS in POSITIONS.
3699 Positions are calculated by `markdown-calc-indents'."
3700 (while (and positions
3701 (not (equal cur-pos (car positions))))
3702 (setq positions (cdr positions)))
3703 (or (cadr positions) 0))
3705 (defun markdown-exdent-find-next-position (cur-pos positions)
3706 "Return the maximal element that precedes CUR-POS from POSITIONS.
3707 Positions are calculated by `markdown-calc-indents'."
3708 (let ((result 0))
3709 (dolist (i positions)
3710 (when (< i cur-pos)
3711 (setq result (max result i))))
3712 result))
3714 (defun markdown-indent-line ()
3715 "Indent the current line using some heuristics.
3716 If the _previous_ command was either `markdown-enter-key' or
3717 `markdown-cycle', then we should cycle to the next
3718 reasonable indentation position. Otherwise, we could have been
3719 called directly by `markdown-enter-key', by an initial call of
3720 `markdown-cycle', or indirectly by `auto-fill-mode'. In
3721 these cases, indent to the default position.
3722 Positions are calculated by `markdown-calc-indents'."
3723 (interactive)
3724 (let ((positions (markdown-calc-indents))
3725 (cur-pos (current-column)))
3726 (if (not (equal this-command 'markdown-cycle))
3727 (indent-line-to (car positions))
3728 (setq positions (sort (delete-dups positions) '<))
3729 (indent-line-to
3730 (markdown-indent-find-next-position cur-pos positions)))))
3732 (defun markdown-calc-indents ()
3733 "Return a list of indentation columns to cycle through.
3734 The first element in the returned list should be considered the
3735 default indentation level. This function does not worry about
3736 duplicate positions, which are handled up by calling functions."
3737 (let (pos prev-line-pos positions)
3739 ;; Indentation of previous line
3740 (setq prev-line-pos (markdown-prev-line-indent))
3741 (setq positions (cons prev-line-pos positions))
3743 ;; Indentation of previous non-list-marker text
3744 (when (setq pos (markdown-prev-non-list-indent))
3745 (setq positions (cons pos positions)))
3747 ;; Indentation required for a pre block in current context
3748 (setq pos (length (markdown-pre-indentation (point))))
3749 (setq positions (cons pos positions))
3751 ;; Indentation of the previous line + tab-width
3752 (if prev-line-pos
3753 (setq positions (cons (+ prev-line-pos tab-width) positions))
3754 (setq positions (cons tab-width positions)))
3756 ;; Indentation of the previous line - tab-width
3757 (if (and prev-line-pos (> prev-line-pos tab-width))
3758 (setq positions (cons (- prev-line-pos tab-width) positions)))
3760 ;; Indentation of all preceeding list markers (when in a list)
3761 (when (setq pos (markdown-calculate-list-levels))
3762 (setq positions (append pos positions)))
3764 ;; First column
3765 (setq positions (cons 0 positions))
3767 ;; Return reversed list
3768 (reverse positions)))
3770 (defun markdown-enter-key ()
3771 "Handle RET according to to the value of `markdown-indent-on-enter'."
3772 (interactive)
3773 (newline)
3774 (when markdown-indent-on-enter
3775 (markdown-indent-line)))
3777 (defun markdown-exdent-or-delete (arg)
3778 "Handle BACKSPACE by cycling through indentation points.
3779 When BACKSPACE is pressed, if there is only whitespace
3780 before the current point, then exdent the line one level.
3781 Otherwise, do normal delete by repeating
3782 `backward-delete-char-untabify' ARG times."
3783 (interactive "*p")
3784 (let ((cur-pos (current-column))
3785 (start-of-indention (save-excursion
3786 (back-to-indentation)
3787 (current-column)))
3788 (positions (markdown-calc-indents)))
3789 (if (and (> cur-pos 0) (= cur-pos start-of-indention))
3790 (indent-line-to (markdown-exdent-find-next-position cur-pos positions))
3791 (backward-delete-char-untabify arg))))
3793 (defun markdown-find-leftmost-column (beg end)
3794 "Find the leftmost column in the region from BEG to END."
3795 (let ((mincol 1000))
3796 (save-excursion
3797 (goto-char beg)
3798 (while (< (point) end)
3799 (back-to-indentation)
3800 (unless (looking-at "[ \t]*$")
3801 (setq mincol (min mincol (current-column))))
3802 (forward-line 1)
3804 mincol))
3806 (defun markdown-indent-region (beg end arg)
3807 "Indent the region from BEG to END using some heuristics.
3808 When ARG is non-nil, exdent the region instead.
3809 See `markdown-indent-line' and `markdown-indent-line'."
3810 (interactive "*r\nP")
3811 (let* ((positions (sort (delete-dups (markdown-calc-indents)) '<))
3812 (leftmostcol (markdown-find-leftmost-column beg end))
3813 (next-pos (if arg
3814 (markdown-exdent-find-next-position leftmostcol positions)
3815 (markdown-indent-find-next-position leftmostcol positions))))
3816 (indent-rigidly beg end (- next-pos leftmostcol))
3817 (setq deactivate-mark nil)))
3819 (defun markdown-exdent-region (beg end)
3820 "Call `markdown-indent-region' on region from BEG to END with prefix."
3821 (interactive "*r")
3822 (markdown-indent-region (region-beginning) (region-end) t))
3825 ;;; Markup Completion =========================================================
3827 (defconst markdown-complete-alist
3828 '((markdown-regex-header-atx . markdown-complete-atx)
3829 (markdown-regex-header-setext . markdown-complete-setext)
3830 (markdown-regex-hr . markdown-complete-hr))
3831 "Association list of form (regexp . function) for markup completion.")
3833 (defun markdown-incomplete-atx-p ()
3834 "Return t if ATX header markup is incomplete and nil otherwise.
3835 Assumes match data is available for `markdown-regex-header-atx'.
3836 Checks that the number of trailing hash marks equals the number of leading
3837 hash marks, that there is only a single space before and after the text,
3838 and that there is no extraneous whitespace in the text."
3839 (save-match-data
3841 ;; Number of starting and ending hash marks differs
3842 (not (= (length (match-string 1)) (length (match-string 3))))
3843 ;; When the header text is not empty...
3844 (and (> (length (match-string 2)) 0)
3845 ;; ...if there are extra leading, trailing, or interior spaces
3846 (or (not (= (match-beginning 2) (1+ (match-end 1))))
3847 (not (= (match-beginning 3) (1+ (match-end 2))))
3848 (string-match "[ \t\n]\\{2\\}" (match-string 2))))
3849 ;; When the header text is empty...
3850 (and (= (length (match-string 2)) 0)
3851 ;; ...if there are too many or too few spaces
3852 (not (= (match-beginning 3) (+ (match-end 1) 2)))))))
3854 (defun markdown-complete-atx ()
3855 "Complete and normalize ATX headers.
3856 Add or remove hash marks to the end of the header to match the
3857 beginning. Ensure that there is only a single space between hash
3858 marks and header text. Removes extraneous whitespace from header text.
3859 Assumes match data is available for `markdown-regex-header-atx'.
3860 Return nil if markup was complete and non-nil if markup was completed."
3861 (when (markdown-incomplete-atx-p)
3862 (let* ((new-marker (make-marker))
3863 (new-marker (set-marker new-marker (match-end 2))))
3864 ;; Hash marks and spacing at end
3865 (goto-char (match-end 2))
3866 (delete-region (match-end 2) (match-end 3))
3867 (insert " " (match-string 1))
3868 ;; Remove extraneous whitespace from title
3869 (replace-match (markdown-compress-whitespace-string (match-string 2))
3870 t t nil 2)
3871 ;; Spacing at beginning
3872 (goto-char (match-end 1))
3873 (delete-region (match-end 1) (match-beginning 2))
3874 (insert " ")
3875 ;; Leave point at end of text
3876 (goto-char new-marker))))
3878 (defun markdown-incomplete-setext-p ()
3879 "Return t if setext header markup is incomplete and nil otherwise.
3880 Assumes match data is available for `markdown-regex-header-setext'.
3881 Checks that length of underline matches text and that there is no
3882 extraneous whitespace in the text."
3883 (save-match-data
3884 (or (not (= (length (match-string 1)) (length (match-string 2))))
3885 (string-match "[ \t\n]\\{2\\}" (match-string 1)))))
3887 (defun markdown-complete-setext ()
3888 "Complete and normalize setext headers.
3889 Add or remove underline characters to match length of header
3890 text. Removes extraneous whitespace from header text. Assumes
3891 match data is available for `markdown-regex-header-setext'.
3892 Return nil if markup was complete and non-nil if markup was completed."
3893 (when (markdown-incomplete-setext-p)
3894 (let* ((text (markdown-compress-whitespace-string (match-string 1)))
3895 (char (char-after (match-beginning 2)))
3896 (level (if (char-equal char ?-) 2 1)))
3897 (goto-char (match-beginning 0))
3898 (delete-region (match-beginning 0) (match-end 0))
3899 (markdown-insert-header level text t)
3900 t)))
3902 (defun markdown-incomplete-hr-p ()
3903 "Return non-nil if hr is not in `markdown-hr-strings' and nil otherwise.
3904 Assumes match data is available for `markdown-regex-hr'."
3905 (not (member (match-string 0) markdown-hr-strings)))
3907 (defun markdown-complete-hr ()
3908 "Complete horizontal rules.
3909 If horizontal rule string is a member of `markdown-hr-strings',
3910 do nothing. Otherwise, replace with the car of
3911 `markdown-hr-strings'.
3912 Assumes match data is available for `markdown-regex-hr'.
3913 Return nil if markup was complete and non-nil if markup was completed."
3914 (when (markdown-incomplete-hr-p)
3915 (replace-match (car markdown-hr-strings))
3918 (defun markdown-complete ()
3919 "Complete markup of object near point or in region when active.
3920 Handle all objects in `markdown-complete-alist', in order.
3921 See `markdown-complete-at-point' and `markdown-complete-region'."
3922 (interactive "*")
3923 (if (markdown-use-region-p)
3924 (markdown-complete-region (region-beginning) (region-end))
3925 (markdown-complete-at-point)))
3927 (defun markdown-complete-at-point ()
3928 "Complete markup of object near point.
3929 Handle all elements of `markdown-complete-alist' in order."
3930 (interactive "*")
3931 (let ((list markdown-complete-alist) found changed)
3932 (while list
3933 (let ((regexp (eval (caar list)))
3934 (function (cdar list)))
3935 (setq list (cdr list))
3936 (when (thing-at-point-looking-at regexp)
3937 (setq found t)
3938 (setq changed (funcall function))
3939 (setq list nil))))
3940 (if found
3941 (or changed (error "Markup at point is complete"))
3942 (error "Nothing to complete at point"))))
3944 (defun markdown-complete-region (beg end)
3945 "Complete markup of objects in region from BEG to END.
3946 Handle all objects in `markdown-complete-alist', in order. Each
3947 match is checked to ensure that a previous regexp does not also
3948 match."
3949 (interactive "*r")
3950 (let ((end-marker (set-marker (make-marker) end))
3951 previous)
3952 (dolist (element markdown-complete-alist)
3953 (let ((regexp (eval (car element)))
3954 (function (cdr element)))
3955 (goto-char beg)
3956 (while (re-search-forward regexp end-marker 'limit)
3957 (when (match-string 0)
3958 ;; Make sure this is not a match for any of the preceding regexps.
3959 ;; This prevents mistaking an HR for a Setext subheading.
3960 (let (match)
3961 (save-match-data
3962 (dolist (prev-regexp previous)
3963 (or match (setq match (looking-back prev-regexp nil)))))
3964 (unless match
3965 (save-excursion (funcall function))))))
3966 (add-to-list 'previous regexp)))))
3968 (defun markdown-complete-buffer ()
3969 "Complete markup for all objects in the current buffer."
3970 (interactive "*")
3971 (markdown-complete-region (point-min) (point-max)))
3974 ;;; Markup Cycling ============================================================
3976 (defun markdown-cycle-atx (arg &optional remove)
3977 "Cycle ATX header markup.
3978 Promote header (decrease level) when ARG is 1 and demote
3979 header (increase level) if arg is -1. When REMOVE is non-nil,
3980 remove the header when the level reaches zero and stop cycling
3981 when it reaches six. Otherwise, perform a proper cycling through
3982 levels one through six. Assumes match data is available for
3983 `markdown-regex-header-atx'."
3984 (let* ((old-level (length (match-string 1)))
3985 (new-level (+ old-level arg))
3986 (text (match-string 2)))
3987 (when (not remove)
3988 (setq new-level (% new-level 6))
3989 (setq new-level (cond ((= new-level 0) 6)
3990 ((< new-level 0) (+ new-level 6))
3991 (t new-level))))
3992 (cond
3993 ((= new-level 0)
3994 (markdown-unwrap-thing-at-point nil 0 2))
3995 ((<= new-level 6)
3996 (goto-char (match-beginning 0))
3997 (delete-region (match-beginning 0) (match-end 0))
3998 (markdown-insert-header new-level text nil)))))
4000 (defun markdown-cycle-setext (arg &optional remove)
4001 "Cycle setext header markup.
4002 Promote header (increase level) when ARG is 1 and demote
4003 header (decrease level or remove) if arg is -1. When demoting a
4004 level-two setext header, replace with a level-three atx header.
4005 When REMOVE is non-nil, remove the header when the level reaches
4006 zero. Otherwise, cycle back to a level six atx header. Assumes
4007 match data is available for `markdown-regex-header-setext'."
4008 (let* ((char (char-after (match-beginning 2)))
4009 (old-level (if (char-equal char ?=) 1 2))
4010 (new-level (+ old-level arg))
4011 (text (match-string 1)))
4012 (when (and (not remove) (= new-level 0))
4013 (setq new-level 6))
4014 (cond
4015 ((= new-level 0)
4016 (markdown-unwrap-thing-at-point nil 0 1))
4017 ((<= new-level 2)
4018 (markdown-insert-header new-level nil t))
4019 ((<= new-level 6)
4020 (markdown-insert-header new-level nil nil)))))
4022 (defun markdown-cycle-hr (arg &optional remove)
4023 "Cycle string used for horizontal rule from `markdown-hr-strings'.
4024 When ARG is 1, cycle forward (demote), and when ARG is -1, cycle
4025 backwards (promote). When REMOVE is non-nil, remove the hr instead
4026 of cycling when the end of the list is reached.
4027 Assumes match data is available for `markdown-regex-hr'."
4028 (let* ((strings (if (= arg -1)
4029 (reverse markdown-hr-strings)
4030 markdown-hr-strings))
4031 (tail (member (match-string 0) strings))
4032 (new (or (cadr tail)
4033 (if remove
4034 (if (= arg 1)
4036 (car tail))
4037 (car strings)))))
4038 (replace-match new)))
4040 (defun markdown-cycle-bold ()
4041 "Cycle bold markup between underscores and asterisks.
4042 Assumes match data is available for `markdown-regex-bold'."
4043 (save-excursion
4044 (let* ((old-delim (match-string 3))
4045 (new-delim (if (string-equal old-delim "**") "__" "**")))
4046 (replace-match new-delim t t nil 3)
4047 (replace-match new-delim t t nil 5))))
4049 (defun markdown-cycle-italic ()
4050 "Cycle italic markup between underscores and asterisks.
4051 Assumes match data is available for `markdown-regex-italic'."
4052 (save-excursion
4053 (let* ((old-delim (match-string 2))
4054 (new-delim (if (string-equal old-delim "*") "_" "*")))
4055 (replace-match new-delim t t nil 2)
4056 (replace-match new-delim t t nil 4))))
4059 ;;; Keymap ====================================================================
4061 (defvar markdown-mode-map
4062 (let ((map (make-keymap)))
4063 ;; Element insertion
4064 (define-key map "\C-c\C-al" 'markdown-insert-link)
4065 (define-key map "\C-c\C-aL" 'markdown-insert-reference-link-dwim)
4066 (define-key map "\C-c\C-au" 'markdown-insert-uri)
4067 (define-key map "\C-c\C-af" 'markdown-insert-footnote)
4068 (define-key map "\C-c\C-aw" 'markdown-insert-wiki-link)
4069 (define-key map "\C-c\C-ii" 'markdown-insert-image)
4070 (define-key map "\C-c\C-iI" 'markdown-insert-reference-image)
4071 (define-key map "\C-c\C-th" 'markdown-insert-header-dwim)
4072 (define-key map "\C-c\C-tH" 'markdown-insert-header-setext-dwim)
4073 (define-key map "\C-c\C-t1" 'markdown-insert-header-atx-1)
4074 (define-key map "\C-c\C-t2" 'markdown-insert-header-atx-2)
4075 (define-key map "\C-c\C-t3" 'markdown-insert-header-atx-3)
4076 (define-key map "\C-c\C-t4" 'markdown-insert-header-atx-4)
4077 (define-key map "\C-c\C-t5" 'markdown-insert-header-atx-5)
4078 (define-key map "\C-c\C-t6" 'markdown-insert-header-atx-6)
4079 (define-key map "\C-c\C-t!" 'markdown-insert-header-setext-1)
4080 (define-key map "\C-c\C-t@" 'markdown-insert-header-setext-2)
4081 (define-key map "\C-c\C-ss" 'markdown-insert-bold)
4082 (define-key map "\C-c\C-se" 'markdown-insert-italic)
4083 (define-key map "\C-c\C-sc" 'markdown-insert-code)
4084 (define-key map "\C-c\C-sb" 'markdown-insert-blockquote)
4085 (define-key map "\C-c\C-sk" 'markdown-insert-kbd)
4086 (define-key map "\C-c\C-s\C-b" 'markdown-blockquote-region)
4087 (define-key map "\C-c\C-sp" 'markdown-insert-pre)
4088 (define-key map "\C-c\C-s\C-p" 'markdown-pre-region)
4089 (define-key map "\C-c\C-sP" 'markdown-insert-gfm-code-block)
4090 (define-key map "\C-c-" 'markdown-insert-hr)
4091 ;; Element insertion (deprecated)
4092 (define-key map "\C-c\C-ar" 'markdown-insert-reference-link-dwim)
4093 (define-key map "\C-c\C-tt" 'markdown-insert-header-setext-1)
4094 (define-key map "\C-c\C-ts" 'markdown-insert-header-setext-2)
4095 ;; Element removal
4096 (define-key map (kbd "C-c C-k") 'markdown-kill-thing-at-point)
4097 ;; Promotion, Demotion, Completion, and Cycling
4098 (define-key map (kbd "C-c C--") 'markdown-promote)
4099 (define-key map (kbd "C-c C-=") 'markdown-demote)
4100 (define-key map (kbd "C-c C-]") 'markdown-complete)
4101 ;; Following and Jumping
4102 (define-key map (kbd "C-c C-o") 'markdown-follow-thing-at-point)
4103 (define-key map (kbd "C-c C-l") 'markdown-jump)
4104 ;; Indentation
4105 (define-key map (kbd "C-m") 'markdown-enter-key)
4106 (define-key map (kbd "DEL") 'markdown-exdent-or-delete)
4107 (define-key map (kbd "C-c >") 'markdown-indent-region)
4108 (define-key map (kbd "C-c <") 'markdown-exdent-region)
4109 ;; Visibility cycling
4110 (define-key map (kbd "TAB") 'markdown-cycle)
4111 (define-key map (kbd "<S-iso-lefttab>") 'markdown-shifttab)
4112 (define-key map (kbd "<S-tab>") 'markdown-shifttab)
4113 (define-key map (kbd "<backtab>") 'markdown-shifttab)
4114 ;; Header navigation
4115 (define-key map (kbd "C-c C-n") 'markdown-next-visible-heading)
4116 (define-key map (kbd "C-c C-p") 'markdown-previous-visible-heading)
4117 (define-key map (kbd "C-c C-f") 'markdown-forward-same-level)
4118 (define-key map (kbd "C-c C-b") 'markdown-backward-same-level)
4119 (define-key map (kbd "C-c C-u") 'markdown-up-heading)
4120 ;; Buffer-wide commands
4121 (define-key map (kbd "C-c C-c m") 'markdown-other-window)
4122 (define-key map (kbd "C-c C-c p") 'markdown-preview)
4123 (define-key map (kbd "C-c C-c e") 'markdown-export)
4124 (define-key map (kbd "C-c C-c v") 'markdown-export-and-preview)
4125 (define-key map (kbd "C-c C-c o") 'markdown-open)
4126 (define-key map (kbd "C-c C-c l") 'markdown-live-preview-mode)
4127 (define-key map (kbd "C-c C-c w") 'markdown-kill-ring-save)
4128 (define-key map (kbd "C-c C-c c") 'markdown-check-refs)
4129 (define-key map (kbd "C-c C-c n") 'markdown-cleanup-list-numbers)
4130 (define-key map (kbd "C-c C-c ]") 'markdown-complete-buffer)
4131 ;; List editing
4132 (define-key map (kbd "M-<up>") 'markdown-move-up)
4133 (define-key map (kbd "M-<down>") 'markdown-move-down)
4134 (define-key map (kbd "M-<left>") 'markdown-promote)
4135 (define-key map (kbd "M-<right>") 'markdown-demote)
4136 (define-key map (kbd "M-<return>") 'markdown-insert-list-item)
4137 (define-key map (kbd "C-c C-j") 'markdown-insert-list-item)
4138 ;; Subtree editing
4139 (define-key map (kbd "M-S-<up>") 'markdown-move-subtree-up)
4140 (define-key map (kbd "M-S-<down>") 'markdown-move-subtree-down)
4141 (define-key map (kbd "M-S-<left>") 'markdown-promote-subtree)
4142 (define-key map (kbd "M-S-<right>") 'markdown-demote-subtree)
4143 ;; Movement
4144 (define-key map (kbd "M-{") 'markdown-backward-paragraph)
4145 (define-key map (kbd "M-}") 'markdown-forward-paragraph)
4146 (define-key map (kbd "M-n") 'markdown-next-link)
4147 (define-key map (kbd "M-p") 'markdown-previous-link)
4148 ;; Alternative keys (in case of problems with the arrow keys)
4149 (define-key map (kbd "C-c C-x u") 'markdown-move-up)
4150 (define-key map (kbd "C-c C-x d") 'markdown-move-down)
4151 (define-key map (kbd "C-c C-x l") 'markdown-promote)
4152 (define-key map (kbd "C-c C-x r") 'markdown-demote)
4153 (define-key map (kbd "C-c C-x m") 'markdown-insert-list-item)
4154 map)
4155 "Keymap for Markdown major mode.")
4157 (defvar gfm-mode-map
4158 (let ((map (make-sparse-keymap)))
4159 (set-keymap-parent map markdown-mode-map)
4160 (define-key map (kbd "C-c C-s d") 'markdown-insert-strike-through)
4161 (define-key map "`" 'markdown-electric-backquote)
4162 map)
4163 "Keymap for `gfm-mode'.
4164 See also `markdown-mode-map'.")
4167 ;;; Menu ==================================================================
4169 (easy-menu-define markdown-mode-menu markdown-mode-map
4170 "Menu for Markdown mode"
4171 '("Markdown"
4172 ("Show/Hide"
4173 ["Cycle visibility" markdown-cycle (markdown-on-heading-p)]
4174 ["Cycle global visibility" markdown-shifttab])
4175 "---"
4176 ["Compile" markdown-other-window]
4177 ["Preview" markdown-preview]
4178 ["Export" markdown-export]
4179 ["Export & View" markdown-export-and-preview]
4180 ["Open" markdown-open]
4181 ["Live Export" markdown-live-preview-mode
4182 :style toggle :selected markdown-live-preview-mode]
4183 ["Kill ring save" markdown-kill-ring-save]
4184 "---"
4185 ("Headings"
4186 ["Automatic" markdown-insert-header-dwim]
4187 ["Automatic (prefer setext)" markdown-insert-header-setext-dwim]
4188 "---"
4189 ["First level setext" markdown-insert-header-setext-1]
4190 ["Second level setext" markdown-insert-header-setext-2]
4191 "---"
4192 ["First level atx" markdown-insert-header-atx-1]
4193 ["Second level atx" markdown-insert-header-atx-2]
4194 ["Third level atx" markdown-insert-header-atx-3]
4195 ["Fourth level atx" markdown-insert-header-atx-4]
4196 ["Fifth level atx" markdown-insert-header-atx-5]
4197 ["Sixth level atx" markdown-insert-header-atx-6])
4198 "---"
4199 ["Bold" markdown-insert-bold]
4200 ["Italic" markdown-insert-italic]
4201 ["Strikethrough" markdown-insert-strike-through]
4202 ["Blockquote" markdown-insert-blockquote]
4203 ["Preformatted" markdown-insert-pre]
4204 ["Code" markdown-insert-code]
4205 "---"
4206 ["Insert inline link" markdown-insert-link]
4207 ["Insert reference link" markdown-insert-reference-link-dwim]
4208 ["Insert URL" markdown-insert-uri]
4209 ["Insert inline image" markdown-insert-image]
4210 ["Insert reference image" markdown-insert-reference-image]
4211 ["Insert list item" markdown-insert-list-item]
4212 ["Insert horizontal rule" markdown-insert-hr]
4213 ["Insert footnote" markdown-insert-footnote]
4214 ["Kill element" markdown-kill-thing-at-point]
4215 "---"
4216 ["Jump" markdown-jump]
4217 ["Follow link" markdown-follow-thing-at-point]
4218 ("Outline"
4219 ["Next visible heading" markdown-next-visible-heading]
4220 ["Previous visible heading" markdown-previous-visible-heading]
4221 ["Forward same level" markdown-forward-same-level]
4222 ["Backward same level" markdown-backward-same-level]
4223 ["Up to parent heading" markdown-up-heading])
4224 "---"
4225 ("Completion and Cycling"
4226 ["Complete" markdown-complete]
4227 ["Promote" markdown-promote]
4228 ["Demote" markdown-demote])
4229 ("List editing"
4230 ["Indent list item" markdown-demote]
4231 ["Exdent list item" markdown-promote])
4232 ("Region shifting"
4233 ["Indent region" markdown-indent-region]
4234 ["Exdent region" markdown-exdent-region])
4235 "---"
4236 ["Check references" markdown-check-refs]
4237 ["Clean up list numbering" markdown-cleanup-list-numbers]
4238 ["Complete markup" markdown-complete-buffer]
4239 "---"
4240 ["Version" markdown-show-version]
4244 ;;; imenu =====================================================================
4246 (defun markdown-imenu-create-nested-index ()
4247 "Create and return a nested imenu index alist for the current buffer.
4248 See `imenu-create-index-function' and `imenu--index-alist' for details."
4249 (let* ((root '(nil . nil))
4250 cur-alist
4251 (cur-level 0)
4252 (empty-heading "-")
4253 (self-heading ".")
4254 hashes pos level heading)
4255 (save-excursion
4256 (goto-char (point-min))
4257 (while (re-search-forward markdown-regex-header (point-max) t)
4258 (unless (markdown-code-block-at-point)
4259 (cond
4260 ((setq heading (match-string-no-properties 1))
4261 (setq pos (match-beginning 1)
4262 level 1))
4263 ((setq heading (match-string-no-properties 3))
4264 (setq pos (match-beginning 3)
4265 level 2))
4266 ((setq hashes (match-string-no-properties 5))
4267 (setq heading (match-string-no-properties 6)
4268 pos (match-beginning 5)
4269 level (length hashes))))
4270 (let ((alist (list (cons heading pos))))
4271 (cond
4272 ((= cur-level level) ; new sibling
4273 (setcdr cur-alist alist)
4274 (setq cur-alist alist))
4275 ((< cur-level level) ; first child
4276 (dotimes (i (- level cur-level 1))
4277 (setq alist (list (cons empty-heading alist))))
4278 (if cur-alist
4279 (let* ((parent (car cur-alist))
4280 (self-pos (cdr parent)))
4281 (setcdr parent (cons (cons self-heading self-pos) alist)))
4282 (setcdr root alist)) ; primogenitor
4283 (setq cur-alist alist)
4284 (setq cur-level level))
4285 (t ; new sibling of an ancestor
4286 (let ((sibling-alist (last (cdr root))))
4287 (dotimes (i (1- level))
4288 (setq sibling-alist (last (cdar sibling-alist))))
4289 (setcdr sibling-alist alist)
4290 (setq cur-alist alist))
4291 (setq cur-level level))))))
4292 (cdr root))))
4294 (defun markdown-imenu-create-flat-index ()
4295 "Create and return a flat imenu index alist for the current buffer.
4296 See `imenu-create-index-function' and `imenu--index-alist' for details."
4297 (let* ((empty-heading "-") index heading pos)
4298 (save-excursion
4299 (goto-char (point-min))
4300 (while (re-search-forward markdown-regex-header (point-max) t)
4301 (cond
4302 ((setq heading (match-string-no-properties 1))
4303 (setq pos (match-beginning 1)))
4304 ((setq heading (match-string-no-properties 3))
4305 (setq pos (match-beginning 3)))
4306 ((setq heading (match-string-no-properties 6))
4307 (setq pos (match-beginning 5))))
4308 (or (> (length heading) 0)
4309 (setq heading empty-heading))
4310 (setq index (append index (list (cons heading pos)))))
4311 index)))
4314 ;;; References ================================================================
4316 (defun markdown-reference-goto-definition ()
4317 "Jump to the definition of the reference at point or create it."
4318 (interactive)
4319 (when (thing-at-point-looking-at markdown-regex-link-reference)
4320 (let* ((text (match-string-no-properties 3))
4321 (reference (match-string-no-properties 6))
4322 (target (downcase (if (string= reference "") text reference)))
4323 (loc (cadr (markdown-reference-definition target))))
4324 (if loc
4325 (goto-char loc)
4326 (goto-char (match-beginning 0))
4327 (markdown-insert-reference-definition target)))))
4329 (defun markdown-reference-find-links (reference)
4330 "Return a list of all links for REFERENCE.
4331 REFERENCE should not include the surrounding square brackets.
4332 Elements of the list have the form (text start line), where
4333 text is the link text, start is the location at the beginning of
4334 the link, and line is the line number on which the link appears."
4335 (let* ((ref-quote (regexp-quote reference))
4336 (regexp (format "!?\\(?:\\[\\(%s\\)\\][ ]?\\[\\]\\|\\[\\([^]]+?\\)\\][ ]?\\[%s\\]\\)"
4337 ref-quote ref-quote))
4338 links)
4339 (save-excursion
4340 (goto-char (point-min))
4341 (while (re-search-forward regexp nil t)
4342 (let* ((text (or (match-string-no-properties 1)
4343 (match-string-no-properties 2)))
4344 (start (match-beginning 0))
4345 (line (markdown-line-number-at-pos)))
4346 (add-to-list 'links (list text start line)))))
4347 links))
4349 (defun markdown-get-undefined-refs ()
4350 "Return a list of undefined Markdown references.
4351 Result is an alist of pairs (reference . occurrences), where
4352 occurrences is itself another alist of pairs (label . line-number).
4353 For example, an alist corresponding to [Nice editor][Emacs] at line 12,
4354 \[GNU Emacs][Emacs] at line 45 and [manual][elisp] at line 127 is
4355 \((\"emacs\" (\"Nice editor\" . 12) (\"GNU Emacs\" . 45)) (\"elisp\" (\"manual\" . 127)))."
4356 (let ((missing))
4357 (save-excursion
4358 (goto-char (point-min))
4359 (while
4360 (re-search-forward markdown-regex-link-reference nil t)
4361 (let* ((text (match-string-no-properties 3))
4362 (reference (match-string-no-properties 6))
4363 (target (downcase (if (string= reference "") text reference))))
4364 (unless (markdown-reference-definition target)
4365 (let ((entry (assoc target missing)))
4366 (if (not entry)
4367 (add-to-list 'missing (cons target
4368 (list (cons text (markdown-line-number-at-pos)))) t)
4369 (setcdr entry
4370 (append (cdr entry) (list (cons text (markdown-line-number-at-pos))))))))))
4371 missing)))
4373 (defconst markdown-reference-check-buffer
4374 "*Undefined references for %buffer%*"
4375 "Pattern for name of buffer for listing undefined references.
4376 The string %buffer% will be replaced by the corresponding
4377 `markdown-mode' buffer name.")
4379 (defun markdown-reference-check-buffer (&optional buffer-name)
4380 "Name and return buffer for reference checking.
4381 BUFFER-NAME is the name of the main buffer being visited."
4382 (or buffer-name (setq buffer-name (buffer-name)))
4383 (let ((refbuf (get-buffer-create (markdown-replace-regexp-in-string
4384 "%buffer%" buffer-name
4385 markdown-reference-check-buffer))))
4386 (with-current-buffer refbuf
4387 (when view-mode
4388 (View-exit-and-edit))
4389 (use-local-map button-buffer-map)
4390 (erase-buffer))
4391 refbuf))
4393 (defconst markdown-reference-links-buffer
4394 "*Reference links for %buffer%*"
4395 "Pattern for name of buffer for listing references.
4396 The string %buffer% will be replaced by the corresponding buffer name.")
4398 (defun markdown-reference-links-buffer (&optional buffer-name)
4399 "Name, setup, and return a buffer for listing links.
4400 BUFFER-NAME is the name of the main buffer being visited."
4401 (or buffer-name (setq buffer-name (buffer-name)))
4402 (let ((linkbuf (get-buffer-create (markdown-replace-regexp-in-string
4403 "%buffer%" buffer-name
4404 markdown-reference-links-buffer))))
4405 (with-current-buffer linkbuf
4406 (when view-mode
4407 (View-exit-and-edit))
4408 (use-local-map button-buffer-map)
4409 (erase-buffer))
4410 linkbuf))
4412 (when (markdown-use-buttons-p)
4413 ;; Add an empty Markdown reference definition to buffer
4414 ;; specified in the 'target-buffer property. The reference name is
4415 ;; the button's label.
4416 (define-button-type 'markdown-undefined-reference-button
4417 'help-echo "mouse-1, RET: create definition for undefined reference"
4418 'follow-link t
4419 'face 'bold
4420 'action (lambda (b)
4421 (let ((buffer (button-get b 'target-buffer))
4422 (line (button-get b 'target-line))
4423 (label (button-label b)))
4424 (switch-to-buffer-other-window buffer)
4425 (goto-char (point-min))
4426 (forward-line line)
4427 (markdown-insert-reference-definition label)
4428 (markdown-check-refs t))))
4430 ;; Jump to line in buffer specified by 'target-buffer property.
4431 ;; Line number is button's 'line property.
4432 (define-button-type 'markdown-goto-line-button
4433 'help-echo "mouse-1, RET: go to line"
4434 'follow-link t
4435 'face 'italic
4436 'action (lambda (b)
4437 (message (button-get b 'buffer))
4438 (switch-to-buffer-other-window (button-get b 'target-buffer))
4439 ;; use call-interactively to silence compiler
4440 (let ((current-prefix-arg (button-get b 'target-line)))
4441 (call-interactively 'goto-line))))
4443 ;; Jumps to a particular link at location given by 'target-char
4444 ;; property in buffer given by 'target-buffer property.
4445 (define-button-type 'markdown-link-button
4446 'help-echo "mouse-1, RET: jump to location of link"
4447 'follow-link t
4448 'face 'bold
4449 'action (lambda (b)
4450 (let ((target (button-get b 'target-buffer))
4451 (loc (button-get b 'target-char)))
4452 (kill-buffer-and-window)
4453 (switch-to-buffer target)
4454 (goto-char loc)))))
4456 (defun markdown-insert-undefined-reference-button (reference oldbuf)
4457 "Insert a button for creating REFERENCE in buffer OLDBUF.
4458 REFERENCE should be a list of the form (reference . occurrences),
4459 as by `markdown-get-undefined-refs'."
4460 (let ((label (car reference)))
4461 (if (markdown-use-buttons-p)
4462 ;; Create a reference button in Emacs 22
4463 (insert-button label
4464 :type 'markdown-undefined-reference-button
4465 'target-buffer oldbuf
4466 'target-line (cdr (car (cdr reference))))
4467 ;; Insert reference as text in Emacs < 22
4468 (insert label))
4469 (insert " (")
4470 (dolist (occurrence (cdr reference))
4471 (let ((line (cdr occurrence)))
4472 (if (markdown-use-buttons-p)
4473 ;; Create a line number button in Emacs 22
4474 (insert-button (number-to-string line)
4475 :type 'markdown-goto-line-button
4476 'target-buffer oldbuf
4477 'target-line line)
4478 ;; Insert line number as text in Emacs < 22
4479 (insert (number-to-string line)))
4480 (insert " ")))
4481 (delete-char -1)
4482 (insert ")")
4483 (newline)))
4485 (defun markdown-insert-link-button (link oldbuf)
4486 "Insert a button for jumping to LINK in buffer OLDBUF.
4487 LINK should be a list of the form (text char line) containing
4488 the link text, location, and line number."
4489 (let ((label (cl-first link))
4490 (char (cl-second link))
4491 (line (cl-third link)))
4492 (if (markdown-use-buttons-p)
4493 ;; Create a reference button in Emacs 22
4494 (insert-button label
4495 :type 'markdown-link-button
4496 'target-buffer oldbuf
4497 'target-char char)
4498 ;; Insert reference as text in Emacs < 22
4499 (insert label))
4500 (insert (format " (line %d)\n" line))))
4502 (defun markdown-reference-goto-link (&optional reference)
4503 "Jump to the location of the first use of REFERENCE."
4504 (interactive)
4505 (unless reference
4506 (if (thing-at-point-looking-at markdown-regex-reference-definition)
4507 (setq reference (match-string-no-properties 2))
4508 (error "No reference definition at point")))
4509 (let ((links (markdown-reference-find-links reference)))
4510 (cond ((= (length links) 1)
4511 (goto-char (cadr (car links))))
4512 ((> (length links) 1)
4513 (let ((oldbuf (current-buffer))
4514 (linkbuf (markdown-reference-links-buffer)))
4515 (with-current-buffer linkbuf
4516 (insert "Links using reference " reference ":\n\n")
4517 (dolist (link (reverse links))
4518 (markdown-insert-link-button link oldbuf)))
4519 (view-buffer-other-window linkbuf)
4520 (goto-char (point-min))
4521 (forward-line 2)))
4523 (error "No links for reference %s" reference)))))
4525 (defun markdown-check-refs (&optional silent)
4526 "Show all undefined Markdown references in current `markdown-mode' buffer.
4527 If SILENT is non-nil, do not message anything when no undefined
4528 references found.
4529 Links which have empty reference definitions are considered to be
4530 defined."
4531 (interactive "P")
4532 (when (not (eq major-mode 'markdown-mode))
4533 (error "Not available in current mode"))
4534 (let ((oldbuf (current-buffer))
4535 (refs (markdown-get-undefined-refs))
4536 (refbuf (markdown-reference-check-buffer)))
4537 (if (null refs)
4538 (progn
4539 (when (not silent)
4540 (message "No undefined references found"))
4541 (kill-buffer refbuf))
4542 (with-current-buffer refbuf
4543 (insert "The following references are undefined:\n\n")
4544 (dolist (ref refs)
4545 (markdown-insert-undefined-reference-button ref oldbuf))
4546 (view-buffer-other-window refbuf)
4547 (goto-char (point-min))
4548 (forward-line 2)))))
4551 ;;; Lists =====================================================================
4553 (defun markdown-insert-list-item (&optional arg)
4554 "Insert a new list item.
4555 If the point is inside unordered list, insert a bullet mark. If
4556 the point is inside ordered list, insert the next number followed
4557 by a period. Use the previous list item to determine the amount
4558 of whitespace to place before and after list markers.
4560 With a \\[universal-argument] prefix (i.e., when ARG is (4)),
4561 decrease the indentation by one level.
4563 With two \\[universal-argument] prefixes (i.e., when ARG is (16)),
4564 increase the indentation by one level."
4565 (interactive "p")
4566 (let (bounds cur-indent marker indent new-indent new-loc)
4567 (save-match-data
4568 ;; Look for a list item on current or previous non-blank line
4569 (save-excursion
4570 (while (and (not (setq bounds (markdown-cur-list-item-bounds)))
4571 (not (bobp))
4572 (markdown-cur-line-blank-p))
4573 (forward-line -1)))
4574 (when bounds
4575 (cond ((save-excursion
4576 (skip-chars-backward " \t")
4577 (looking-at markdown-regex-list))
4578 (beginning-of-line)
4579 (insert "\n")
4580 (forward-line -1))
4581 ((not (markdown-cur-line-blank-p))
4582 (newline)))
4583 (setq new-loc (point)))
4584 ;; Look ahead for a list item on next non-blank line
4585 (unless bounds
4586 (save-excursion
4587 (while (and (null bounds)
4588 (not (eobp))
4589 (markdown-cur-line-blank-p))
4590 (forward-line)
4591 (setq bounds (markdown-cur-list-item-bounds))))
4592 (when bounds
4593 (setq new-loc (point))
4594 (unless (markdown-cur-line-blank-p)
4595 (newline))))
4596 (if (not bounds)
4597 ;; When not in a list, start a new unordered one
4598 (progn
4599 (unless (markdown-cur-line-blank-p)
4600 (insert "\n"))
4601 (insert markdown-unordered-list-item-prefix))
4602 ;; Compute indentation and marker for new list item
4603 (setq cur-indent (nth 2 bounds))
4604 (setq marker (nth 4 bounds))
4605 (cond
4606 ;; Dedent: decrement indentation, find previous marker.
4607 ((= arg 4)
4608 (setq indent (max (- cur-indent 4) 0))
4609 (let ((prev-bounds
4610 (save-excursion
4611 (when (markdown-prev-list-item (- (nth 3 bounds) 1))
4612 (markdown-cur-list-item-bounds)))))
4613 (when prev-bounds
4614 (setq marker (nth 4 prev-bounds)))))
4615 ;; Indent: increment indentation by 4, use same marker.
4616 ((= arg 16) (setq indent (+ cur-indent 4)))
4617 ;; Same level: keep current indentation and marker.
4618 (t (setq indent cur-indent)))
4619 (setq new-indent (make-string indent 32))
4620 (goto-char new-loc)
4621 (cond
4622 ;; Ordered list
4623 ((string-match "[0-9]" marker)
4624 (if (= arg 16) ;; starting a new column indented one more level
4625 (insert (concat new-indent "1. "))
4626 ;; travel up to the last item and pick the correct number. If
4627 ;; the argument was nil, "new-indent = cur-indent" is the same,
4628 ;; so we don't need special treatment. Neat.
4629 (save-excursion
4630 (while (and (not (looking-at (concat new-indent "\\([0-9]+\\)\\(\\.[ \t]*\\)")))
4631 (>= (forward-line -1) 0))))
4632 (let* ((old-prefix (match-string 1))
4633 (old-spacing (match-string 2))
4634 (new-prefix (if old-prefix
4635 (int-to-string (1+ (string-to-number old-prefix)))
4636 "1"))
4637 (space-adjust (- (length old-prefix) (length new-prefix)))
4638 (new-spacing (if (and (match-string 2)
4639 (not (string-match "\t" old-spacing))
4640 (< space-adjust 0)
4641 (> space-adjust (- 1 (length (match-string 2)))))
4642 (substring (match-string 2) 0 space-adjust)
4643 (or old-spacing ". "))))
4644 (insert (concat new-indent new-prefix new-spacing)))))
4645 ;; Unordered list
4646 ((string-match "[\\*\\+-]" marker)
4647 (insert new-indent marker)))))))
4649 (defun markdown-move-list-item-up ()
4650 "Move the current list item up in the list when possible."
4651 (interactive)
4652 (let (cur prev old)
4653 (when (setq cur (markdown-cur-list-item-bounds))
4654 (setq old (point))
4655 (goto-char (nth 0 cur))
4656 (if (markdown-prev-list-item (nth 3 cur))
4657 (progn
4658 (setq prev (markdown-cur-list-item-bounds))
4659 (condition-case nil
4660 (progn
4661 (transpose-regions (nth 0 prev) (nth 1 prev)
4662 (nth 0 cur) (nth 1 cur) t)
4663 (goto-char (+ (nth 0 prev) (- old (nth 0 cur)))))
4664 ;; Catch error in case regions overlap.
4665 (error (goto-char old))))
4666 (goto-char old)))))
4668 (defun markdown-move-list-item-down ()
4669 "Move the current list item down in the list when possible."
4670 (interactive)
4671 (let (cur next old)
4672 (when (setq cur (markdown-cur-list-item-bounds))
4673 (setq old (point))
4674 (if (markdown-next-list-item (nth 3 cur))
4675 (progn
4676 (setq next (markdown-cur-list-item-bounds))
4677 (condition-case nil
4678 (progn
4679 (transpose-regions (nth 0 cur) (nth 1 cur)
4680 (nth 0 next) (nth 1 next) nil)
4681 (goto-char (+ old (- (nth 1 next) (nth 1 cur)))))
4682 ;; Catch error in case regions overlap.
4683 (error (goto-char old))))
4684 (goto-char old)))))
4686 (defun markdown-demote-list-item (&optional bounds)
4687 "Indent (or demote) the current list item.
4688 Optionally, BOUNDS of the current list item may be provided if available."
4689 (interactive)
4690 (when (or bounds (setq bounds (markdown-cur-list-item-bounds)))
4691 (save-excursion
4692 (save-match-data
4693 (let ((end-marker (set-marker (make-marker) (nth 1 bounds))))
4694 (goto-char (nth 0 bounds))
4695 (while (< (point) end-marker)
4696 (unless (markdown-cur-line-blank-p)
4697 (insert (make-string markdown-list-indent-width ? )))
4698 (forward-line)))))))
4700 (defun markdown-promote-list-item (&optional bounds)
4701 "Unindent (or promote) the current list item.
4702 Optionally, BOUNDS of the current list item may be provided if available."
4703 (interactive)
4704 (when (or bounds (setq bounds (markdown-cur-list-item-bounds)))
4705 (save-excursion
4706 (save-match-data
4707 (let ((end-marker (set-marker (make-marker) (nth 1 bounds)))
4708 num regexp)
4709 (goto-char (nth 0 bounds))
4710 (when (looking-at (format "^[ ]\\{1,%d\\}"
4711 markdown-list-indent-width))
4712 (setq num (- (match-end 0) (match-beginning 0)))
4713 (setq regexp (format "^[ ]\\{1,%d\\}" num))
4714 (while (and (< (point) end-marker)
4715 (re-search-forward regexp end-marker t))
4716 (replace-match "" nil nil)
4717 (forward-line))))))))
4719 (defun markdown-cleanup-list-numbers-level (&optional pfx)
4720 "Update the numbering for level PFX (as a string of spaces).
4722 Assume that the previously found match was for a numbered item in
4723 a list."
4724 (let ((cpfx pfx)
4725 (idx 0)
4726 (continue t)
4727 (step t)
4728 (sep nil))
4729 (while (and continue (not (eobp)))
4730 (setq step t)
4731 (cond
4732 ((looking-at "^\\([\s-]*\\)[0-9]+\\. ")
4733 (setq cpfx (match-string-no-properties 1))
4734 (cond
4735 ((string= cpfx pfx)
4736 (replace-match
4737 (concat pfx (number-to-string (setq idx (1+ idx))) ". "))
4738 (setq sep nil))
4739 ;; indented a level
4740 ((string< pfx cpfx)
4741 (setq sep (markdown-cleanup-list-numbers-level cpfx))
4742 (setq step nil))
4743 ;; exit the loop
4745 (setq step nil)
4746 (setq continue nil))))
4748 ((looking-at "^\\([\s-]*\\)[^ \t\n\r].*$")
4749 (setq cpfx (match-string-no-properties 1))
4750 (cond
4751 ;; reset if separated before
4752 ((string= cpfx pfx) (when sep (setq idx 0)))
4753 ((string< cpfx pfx)
4754 (setq step nil)
4755 (setq continue nil))))
4756 (t (setq sep t)))
4758 (when step
4759 (beginning-of-line)
4760 (setq continue (= (forward-line) 0))))
4761 sep))
4763 (defun markdown-cleanup-list-numbers ()
4764 "Update the numbering of ordered lists."
4765 (interactive)
4766 (save-excursion
4767 (goto-char (point-min))
4768 (markdown-cleanup-list-numbers-level "")))
4771 ;;; Movement ==================================================================
4773 (defun markdown-beginning-of-defun (&optional arg)
4774 "`beginning-of-defun-function' for Markdown.
4775 Move backward to the beginning of the current or previous section.
4776 When ARG is non-nil, repeat that many times. When ARG is negative,
4777 move forward to the ARG-th following section."
4778 (interactive "P")
4779 (or arg (setq arg 1))
4780 (forward-char 1)
4781 (or (re-search-backward markdown-regex-header nil t arg)
4782 (goto-char (point-min))))
4784 (defun markdown-end-of-defun (&optional arg)
4785 "`end-of-defun-function' for Markdown.
4786 Move forward to the end of the current or following section.
4787 When ARG is non-nil, repeat that many times. When ARG is negative,
4788 move back to the ARG-th preceding section."
4789 (interactive "P")
4790 (or arg (setq arg 1))
4791 (when (looking-at markdown-regex-header)
4792 (goto-char (match-beginning 0))
4793 (forward-char 1))
4794 (if (re-search-forward markdown-regex-header nil t arg)
4795 (goto-char (match-beginning 0))
4796 (goto-char (point-max)))
4797 (skip-syntax-backward "-"))
4799 (defun markdown-beginning-of-block ()
4800 "Move the point to the start of the previous text block."
4801 (interactive)
4802 (if (re-search-backward markdown-regex-block-separator nil t)
4803 (goto-char (or (match-end 2) (match-end 0)))
4804 (goto-char (point-min))))
4806 (defun markdown-end-of-block ()
4807 "Move the point to the start of the next text block."
4808 (interactive)
4809 (beginning-of-line)
4810 (skip-syntax-forward "-")
4811 (when (= (point) (point-min))
4812 (forward-char))
4813 (if (re-search-forward markdown-regex-block-separator nil t)
4814 (goto-char (or (match-end 2) (match-end 0)))
4815 (goto-char (point-max)))
4816 (skip-syntax-backward "-")
4817 (forward-line))
4819 (defun markdown-forward-paragraph (arg)
4820 "Move forward one or more paragraphs or by one block.
4821 When ARG is nil or a numeric prefix, call `forward-paragraph'
4822 with ARG. When called with \\[universal-argument], call
4823 `markdown-end-of-block' instead."
4824 (interactive "P")
4825 (or arg (setq arg 1))
4826 (cond ((integerp arg)
4827 (forward-paragraph arg))
4828 ((equal arg '(4))
4829 (markdown-end-of-block))))
4831 (defun markdown-backward-paragraph (arg)
4832 "Move backward one or more paragraphs or by one block.
4833 When ARG is nil or a numeric prefix, call `backward-paragraph'
4834 with ARG. When called with \\[universal-argument], call
4835 `markdown-beginning-of-block' instead."
4836 (interactive "P")
4837 (or arg (setq arg 1))
4838 (cond ((integerp arg)
4839 (backward-paragraph arg))
4840 ((equal arg '(4))
4841 (markdown-beginning-of-block))))
4843 (defun markdown-end-of-block-element ()
4844 "Move the point to the start of the next block unit.
4845 Stops at blank lines, list items, headers, and horizontal rules."
4846 (interactive)
4847 (forward-line)
4848 (while (and (or (not (markdown-prev-line-blank-p))
4849 (markdown-cur-line-blank-p))
4850 (not (or (looking-at markdown-regex-list)
4851 (looking-at markdown-regex-header)
4852 (looking-at markdown-regex-hr)))
4853 (not (eobp)))
4854 (forward-line)))
4856 (defun markdown-next-link ()
4857 "Jump to next inline, reference, or wiki link.
4858 If successful, return point. Otherwise, return nil.
4859 See `markdown-wiki-link-p' and `markdown-previous-wiki-link'."
4860 (interactive)
4861 (let ((opoint (point)))
4862 (when (or (markdown-link-p) (markdown-wiki-link-p))
4863 ;; At a link already, move past it.
4864 (goto-char (+ (match-end 0) 1)))
4865 ;; Search for the next wiki link and move to the beginning.
4866 (while (and (re-search-forward markdown-regex-link-generic nil t)
4867 (markdown-code-block-at-point)
4868 (< (point) (point-max))))
4869 (if (and (not (eq (point) opoint))
4870 (or (markdown-link-p) (markdown-wiki-link-p)))
4871 ;; Group 1 will move past non-escape character in wiki link regexp.
4872 ;; Go to beginning of group zero for all other link types.
4873 (goto-char (or (match-beginning 1) (match-beginning 0)))
4874 (goto-char opoint)
4875 nil)))
4877 (defun markdown-previous-link ()
4878 "Jump to previous wiki link.
4879 If successful, return point. Otherwise, return nil.
4880 See `markdown-wiki-link-p' and `markdown-next-wiki-link'."
4881 (interactive)
4882 (let ((opoint (point)))
4883 (while (and (re-search-backward markdown-regex-link-generic nil t)
4884 (markdown-code-block-at-point)
4885 (> (point) (point-min))))
4886 (if (and (not (eq (point) opoint))
4887 (or (markdown-link-p) (markdown-wiki-link-p)))
4888 (goto-char (or (match-beginning 1) (match-beginning 0)))
4889 (goto-char opoint)
4890 nil)))
4892 (defun markdown-next-heading ()
4893 "Move to the next heading line of any level.
4894 With argument, repeats or can move backward if negative."
4895 (let ((pos (outline-next-heading)))
4896 (while (markdown-code-block-at-point)
4897 (setq pos (outline-next-heading)))
4898 pos))
4900 (defun markdown-previous-heading ()
4901 "Move to the previous heading line of any level.
4902 With argument, repeats or can move backward if negative."
4903 (let ((pos (outline-previous-heading)))
4904 (while (markdown-code-block-at-point)
4905 (setq pos (outline-previous-heading)))
4906 pos))
4909 ;;; Outline ===================================================================
4911 (defun markdown-move-heading-common (move-fn &optional arg)
4912 "Wrapper for `outline-mode' functions to skip false positives.
4913 For example, headings inside preformatted code blocks may match
4914 `outline-regexp' but should not be considered as headings."
4915 (funcall move-fn arg)
4916 (let ((prev -1))
4917 (while (and (/= prev (point)) (markdown-code-block-at-point))
4918 (setq prev (point))
4919 (funcall move-fn arg))))
4921 (defun markdown-next-visible-heading (arg)
4922 "Move to the next visible heading line of any level.
4923 With argument, repeats or can move backward if negative."
4924 (interactive "p")
4925 (markdown-move-heading-common 'outline-next-visible-heading arg))
4927 (defun markdown-previous-visible-heading (arg)
4928 "Move to the previous visible heading line of any level.
4929 With argument, repeats or can move backward if negative."
4930 (interactive "p")
4931 (markdown-move-heading-common 'outline-previous-visible-heading arg))
4933 (defun markdown-forward-same-level (arg)
4934 "Move forward to the ARG'th heading at same level as this one.
4935 Stop at the first and last headings of a superior heading."
4936 (interactive "p")
4937 (markdown-move-heading-common 'outline-forward-same-level arg))
4939 (defun markdown-back-to-heading-over-code-block (&optional invisible-ok)
4940 (beginning-of-line)
4941 (or (and (outline-on-heading-p invisible-ok)
4942 (not (markdown-code-block-at-point)))
4943 (let ((header-re (concat "^\\(?:" outline-regexp "\\)"))
4944 found)
4945 (save-excursion
4946 (while (not found)
4947 (let (finish)
4948 (while (and (not finish) (re-search-backward header-re nil t))
4949 (when (and (or invisible-ok (not (outline-invisible-p)))
4950 (not (markdown-code-block-at-point)))
4951 (setq finish t)))
4952 (if (not finish)
4953 (error "Before first heading")
4954 (setq found (point))))))
4955 (goto-char found)
4956 found)))
4958 (defun markdown-backward-same-level (arg)
4959 "Move backward to the ARG'th heading at same level as this one.
4960 Stop at the first and last headings of a superior heading."
4961 (interactive "p")
4962 (markdown-back-to-heading-over-code-block)
4963 (while (> arg 0)
4964 (let ((point-to-move-to (save-excursion
4965 (outline-get-last-sibling))))
4966 (if point-to-move-to
4967 (progn
4968 (goto-char point-to-move-to)
4969 (setq arg (1- arg)))
4970 (error "No previous same-level heading")))))
4972 (defun markdown-up-heading (arg)
4973 "Move to the visible heading line of which the present line is a subheading.
4974 With argument, move up ARG levels."
4975 (interactive "p")
4976 (markdown-move-heading-common 'outline-up-heading arg))
4978 (defun markdown-back-to-heading (&optional invisible-ok)
4979 "Move to previous heading line, or beg of this line if it's a heading.
4980 Only visible heading lines are considered, unless INVISIBLE-OK is non-nil."
4981 (markdown-move-heading-common 'outline-back-to-heading invisible-ok))
4983 (defalias 'markdown-end-of-heading 'outline-end-of-heading)
4985 (defun markdown-on-heading-p ()
4986 "Return t if point is on a (visible) heading line."
4987 (get-text-property (point) 'markdown-heading))
4989 (defun markdown-end-of-subtree (&optional invisible-OK)
4990 "Move to the end of the current subtree.
4991 Only visible heading lines are considered, unless INVISIBLE-OK is
4992 non-nil.
4993 Derived from `org-end-of-subtree'."
4994 (markdown-back-to-heading invisible-OK)
4995 (let ((first t)
4996 (level (funcall outline-level)))
4997 (while (and (not (eobp))
4998 (or first (> (funcall outline-level) level)))
4999 (setq first nil)
5000 (markdown-next-heading))
5001 (if (memq (preceding-char) '(?\n ?\^M))
5002 (progn
5003 ;; Go to end of line before heading
5004 (forward-char -1)
5005 (if (memq (preceding-char) '(?\n ?\^M))
5006 ;; leave blank line before heading
5007 (forward-char -1)))))
5008 (point))
5010 (defun markdown-outline-fix-visibility ()
5011 "Hide any false positive headings that should not be shown.
5012 For example, headings inside preformatted code blocks may match
5013 `outline-regexp' but should not be shown as headings when cycling."
5014 (save-excursion
5015 (goto-char (point-min))
5016 (unless (outline-on-heading-p)
5017 (outline-next-visible-heading 1))
5018 (while (< (point) (point-max))
5019 (when (markdown-code-block-at-point)
5020 (outline-flag-region (1- (point-at-bol)) (point-at-eol) t))
5021 (outline-next-visible-heading 1))))
5023 (defvar markdown-cycle-global-status 1)
5024 (defvar markdown-cycle-subtree-status nil)
5026 (defun markdown-next-preface ()
5027 (let (finish)
5028 (while (and (not finish) (re-search-forward (concat "\n\\(?:" outline-regexp "\\)")
5029 nil 'move))
5030 (unless (markdown-code-block-at-point)
5031 (goto-char (match-beginning 0))
5032 (setq finish t))))
5033 (when (and (bolp) (or outline-blank-line (eobp)) (not (bobp)))
5034 (forward-char -1)))
5036 (defun markdown-show-entry ()
5037 (save-excursion
5038 (outline-back-to-heading t)
5039 (outline-flag-region (1- (point))
5040 (progn
5041 (markdown-next-preface)
5042 (if (= 1 (- (point-max) (point)))
5043 (point-max)
5044 (point)))
5045 nil)))
5047 (defun markdown-cycle (&optional arg)
5048 "Visibility cycling for Markdown mode.
5049 If ARG is t, perform global visibility cycling. If the point is
5050 at an atx-style header, cycle visibility of the corresponding
5051 subtree. Otherwise, insert a tab using `indent-relative'.
5052 Derived from `org-cycle'."
5053 (interactive "P")
5054 (cond
5055 ((eq arg t) ;; Global cycling
5056 (cond
5057 ((and (eq last-command this-command)
5058 (eq markdown-cycle-global-status 2))
5059 ;; Move from overview to contents
5060 (markdown-hide-sublevels 1)
5061 (message "CONTENTS")
5062 (setq markdown-cycle-global-status 3)
5063 (markdown-outline-fix-visibility))
5065 ((and (eq last-command this-command)
5066 (eq markdown-cycle-global-status 3))
5067 ;; Move from contents to all
5068 (markdown-show-all)
5069 (message "SHOW ALL")
5070 (setq markdown-cycle-global-status 1))
5073 ;; Defaults to overview
5074 (markdown-hide-body)
5075 (message "OVERVIEW")
5076 (setq markdown-cycle-global-status 2)
5077 (markdown-outline-fix-visibility))))
5079 ((save-excursion (beginning-of-line 1) (markdown-on-heading-p))
5080 ;; At a heading: rotate between three different views
5081 (markdown-back-to-heading)
5082 (let ((goal-column 0) eoh eol eos)
5083 ;; Determine boundaries
5084 (save-excursion
5085 (markdown-back-to-heading)
5086 (save-excursion
5087 (beginning-of-line 2)
5088 (while (and (not (eobp)) ;; this is like `next-line'
5089 (get-char-property (1- (point)) 'invisible))
5090 (beginning-of-line 2)) (setq eol (point)))
5091 (markdown-end-of-heading) (setq eoh (point))
5092 (markdown-end-of-subtree t)
5093 (skip-chars-forward " \t\n")
5094 (beginning-of-line 1) ; in case this is an item
5095 (setq eos (1- (point))))
5096 ;; Find out what to do next and set `this-command'
5097 (cond
5098 ((= eos eoh)
5099 ;; Nothing is hidden behind this heading
5100 (message "EMPTY ENTRY")
5101 (setq markdown-cycle-subtree-status nil))
5102 ((>= eol eos)
5103 ;; Entire subtree is hidden in one line: open it
5104 (markdown-show-entry)
5105 (markdown-show-children)
5106 (message "CHILDREN")
5107 (setq markdown-cycle-subtree-status 'children))
5108 ((and (eq last-command this-command)
5109 (eq markdown-cycle-subtree-status 'children))
5110 ;; We just showed the children, now show everything.
5111 (markdown-show-subtree)
5112 (message "SUBTREE")
5113 (setq markdown-cycle-subtree-status 'subtree))
5115 ;; Default action: hide the subtree.
5116 (markdown-hide-subtree)
5117 (message "FOLDED")
5118 (setq markdown-cycle-subtree-status 'folded)))))
5121 (indent-for-tab-command))))
5123 (defun markdown-shifttab ()
5124 "Global visibility cycling.
5125 Calls `markdown-cycle' with argument t."
5126 (interactive)
5127 (markdown-cycle t))
5129 (defun markdown-outline-level ()
5130 "Return the depth to which a statement is nested in the outline."
5131 (cond
5132 ((markdown-code-block-at-point) 7)
5133 ((match-end 1) 1)
5134 ((match-end 3) 2)
5135 ((- (match-end 5) (match-beginning 5)))))
5137 (defun markdown-promote-subtree (&optional arg)
5138 "Promote the current subtree of ATX headings.
5139 Note that Markdown does not support heading levels higher than six
5140 and therefore level-six headings will not be promoted further."
5141 (interactive "*P")
5142 (save-excursion
5143 (when (and (or (thing-at-point-looking-at markdown-regex-header-atx)
5144 (re-search-backward markdown-regex-header-atx nil t))
5145 (not (markdown-code-block-at-point)))
5146 (let ((level (length (match-string 1)))
5147 (promote-or-demote (if arg 1 -1))
5148 (remove 't))
5149 (markdown-cycle-atx promote-or-demote remove)
5150 (catch 'end-of-subtree
5151 (while (markdown-next-heading)
5152 ;; Exit if this not a higher level heading; promote otherwise.
5153 (if (and (looking-at markdown-regex-header-atx)
5154 (<= (length (match-string-no-properties 1)) level))
5155 (throw 'end-of-subtree nil)
5156 (markdown-cycle-atx promote-or-demote remove))))))))
5158 (defun markdown-demote-subtree ()
5159 "Demote the current subtree of ATX headings."
5160 (interactive)
5161 (markdown-promote-subtree t))
5163 (defun markdown-move-subtree-up ()
5164 "Move the current subtree of ATX headings up."
5165 (interactive)
5166 (outline-move-subtree-up 1))
5168 (defun markdown-move-subtree-down ()
5169 "Move the current subtree of ATX headings down."
5170 (interactive)
5171 (outline-move-subtree-down 1))
5174 ;;; Generic Structure Editing, Completion, and Cycling Commands ===============
5176 (defun markdown-move-up ()
5177 "Move list item up.
5178 Calls `markdown-move-list-item-up'."
5179 (interactive)
5180 (markdown-move-list-item-up))
5182 (defun markdown-move-down ()
5183 "Move list item down.
5184 Calls `markdown-move-list-item-down'."
5185 (interactive)
5186 (markdown-move-list-item-down))
5188 (defun markdown-promote ()
5189 "Either promote header or list item at point or cycle markup.
5190 See `markdown-cycle-atx', `markdown-cycle-setext', and
5191 `markdown-promote-list-item'."
5192 (interactive)
5193 (let (bounds)
5194 (cond
5195 ;; Promote atx header
5196 ((thing-at-point-looking-at markdown-regex-header-atx)
5197 (markdown-cycle-atx -1))
5198 ;; Promote setext header
5199 ((thing-at-point-looking-at markdown-regex-header-setext)
5200 (markdown-cycle-setext -1))
5201 ;; Promote horizonal rule
5202 ((thing-at-point-looking-at markdown-regex-hr)
5203 (markdown-cycle-hr -1))
5204 ;; Promote list item
5205 ((setq bounds (markdown-cur-list-item-bounds))
5206 (markdown-promote-list-item))
5207 ;; Promote bold
5208 ((thing-at-point-looking-at markdown-regex-bold)
5209 (markdown-cycle-bold))
5210 ;; Promote italic
5211 ((thing-at-point-looking-at markdown-regex-italic)
5212 (markdown-cycle-italic))
5214 (error "Nothing to promote at point")))))
5216 (defun markdown-demote ()
5217 "Either demote header or list item at point or cycle or remove markup.
5218 See `markdown-cycle-atx', `markdown-cycle-setext', and
5219 `markdown-demote-list-item'."
5220 (interactive)
5221 (let (bounds)
5222 (cond
5223 ;; Demote atx header
5224 ((thing-at-point-looking-at markdown-regex-header-atx)
5225 (markdown-cycle-atx 1))
5226 ;; Demote setext header
5227 ((thing-at-point-looking-at markdown-regex-header-setext)
5228 (markdown-cycle-setext 1))
5229 ;; Demote horizonal rule
5230 ((thing-at-point-looking-at markdown-regex-hr)
5231 (markdown-cycle-hr 1))
5232 ;; Demote list item
5233 ((setq bounds (markdown-cur-list-item-bounds))
5234 (markdown-demote-list-item))
5235 ;; Demote bold
5236 ((thing-at-point-looking-at markdown-regex-bold)
5237 (markdown-cycle-bold))
5238 ;; Demote italic
5239 ((thing-at-point-looking-at markdown-regex-italic)
5240 (markdown-cycle-italic))
5242 (error "Nothing to demote at point")))))
5245 ;;; Commands ==================================================================
5247 (defun markdown (&optional output-buffer-name)
5248 "Run `markdown-command' on buffer, sending output to OUTPUT-BUFFER-NAME.
5249 The output buffer name defaults to `markdown-output-buffer-name'.
5250 Return the name of the output buffer used."
5251 (interactive)
5252 (save-window-excursion
5253 (let ((begin-region)
5254 (end-region))
5255 (if (markdown-use-region-p)
5256 (setq begin-region (region-beginning)
5257 end-region (region-end))
5258 (setq begin-region (point-min)
5259 end-region (point-max)))
5261 (unless output-buffer-name
5262 (setq output-buffer-name markdown-output-buffer-name))
5263 (cond
5264 ;; Handle case when `markdown-command' does not read from stdin
5265 (markdown-command-needs-filename
5266 (if (not buffer-file-name)
5267 (error "Must be visiting a file")
5268 (shell-command (concat markdown-command " "
5269 (shell-quote-argument buffer-file-name))
5270 output-buffer-name)))
5271 ;; Pass region to `markdown-command' via stdin
5273 (shell-command-on-region begin-region end-region markdown-command
5274 output-buffer-name))))
5275 output-buffer-name))
5277 (defun markdown-standalone (&optional output-buffer-name)
5278 "Special function to provide standalone HTML output.
5279 Insert the output in the buffer named OUTPUT-BUFFER-NAME."
5280 (interactive)
5281 (setq output-buffer-name (markdown output-buffer-name))
5282 (with-current-buffer output-buffer-name
5283 (set-buffer output-buffer-name)
5284 (unless (markdown-output-standalone-p)
5285 (markdown-add-xhtml-header-and-footer output-buffer-name))
5286 (goto-char (point-min))
5287 (html-mode))
5288 output-buffer-name)
5290 (defun markdown-other-window (&optional output-buffer-name)
5291 "Run `markdown-command' on current buffer and display in other window.
5292 When OUTPUT-BUFFER-NAME is given, insert the output in the buffer with
5293 that name."
5294 (interactive)
5295 (markdown-display-buffer-other-window
5296 (markdown-standalone output-buffer-name)))
5298 (defun markdown-output-standalone-p ()
5299 "Determine whether `markdown-command' output is standalone XHTML.
5300 Standalone XHTML output is identified by an occurrence of
5301 `markdown-xhtml-standalone-regexp' in the first five lines of output."
5302 (save-excursion
5303 (goto-char (point-min))
5304 (re-search-forward
5305 markdown-xhtml-standalone-regexp
5306 (save-excursion (goto-char (point-min)) (forward-line 4) (point))
5307 t)))
5309 (defun markdown-stylesheet-link-string (stylesheet-path)
5310 (concat "<link rel=\"stylesheet\" type=\"text/css\" media=\"all\" href=\""
5311 stylesheet-path
5312 "\" />"))
5314 (defun markdown-add-xhtml-header-and-footer (title)
5315 "Wrap XHTML header and footer with given TITLE around current buffer."
5316 (goto-char (point-min))
5317 (insert "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"
5318 "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"\n"
5319 "\t\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n\n"
5320 "<html xmlns=\"http://www.w3.org/1999/xhtml\">\n\n"
5321 "<head>\n<title>")
5322 (insert title)
5323 (insert "</title>\n")
5324 (when (> (length markdown-content-type) 0)
5325 (insert
5326 (format
5327 "<meta http-equiv=\"Content-Type\" content=\"%s;charset=%s\"/>\n"
5328 markdown-content-type
5329 (or (and markdown-coding-system
5330 (fboundp 'coding-system-get)
5331 (coding-system-get markdown-coding-system
5332 'mime-charset))
5333 (and (fboundp 'coding-system-get)
5334 (coding-system-get buffer-file-coding-system
5335 'mime-charset))
5336 "iso-8859-1"))))
5337 (if (> (length markdown-css-paths) 0)
5338 (insert (mapconcat 'markdown-stylesheet-link-string markdown-css-paths "\n")))
5339 (when (> (length markdown-xhtml-header-content) 0)
5340 (insert markdown-xhtml-header-content))
5341 (insert "\n</head>\n\n"
5342 "<body>\n\n")
5343 (goto-char (point-max))
5344 (insert "\n"
5345 "</body>\n"
5346 "</html>\n"))
5348 (defun markdown-preview (&optional output-buffer-name)
5349 "Run `markdown-command' on the current buffer and view output in browser.
5350 When OUTPUT-BUFFER-NAME is given, insert the output in the buffer with
5351 that name."
5352 (interactive)
5353 (browse-url-of-buffer (markdown-standalone markdown-output-buffer-name)))
5355 (defun markdown-export-file-name (&optional extension)
5356 "Attempt to generate a filename for Markdown output.
5357 The file extension will be EXTENSION if given, or .html by default.
5358 If the current buffer is visiting a file, we construct a new
5359 output filename based on that filename. Otherwise, return nil."
5360 (when (buffer-file-name)
5361 (unless extension
5362 (setq extension ".html"))
5363 (let ((candidate
5364 (concat
5365 (cond
5366 ((buffer-file-name)
5367 (file-name-sans-extension (buffer-file-name)))
5368 (t (buffer-name)))
5369 extension)))
5370 (cond
5371 ((equal candidate (buffer-file-name))
5372 (concat candidate extension))
5374 candidate)))))
5376 (defun markdown-export (&optional output-file)
5377 "Run Markdown on the current buffer, save to file, and return the filename.
5378 If OUTPUT-FILE is given, use that as the filename. Otherwise, use the filename
5379 generated by `markdown-export-file-name', which will be constructed using the
5380 current filename, but with the extension removed and replaced with .html."
5381 (interactive)
5382 (unless output-file
5383 (setq output-file (markdown-export-file-name ".html")))
5384 (when output-file
5385 (let* ((init-buf (current-buffer))
5386 (init-point (point))
5387 (init-buf-string (buffer-string))
5388 (output-buffer (find-file-noselect output-file))
5389 (output-buffer-name (buffer-name output-buffer)))
5390 (run-hooks 'markdown-before-export-hook)
5391 (markdown-standalone output-buffer-name)
5392 (with-current-buffer output-buffer
5393 (run-hooks 'markdown-after-export-hook)
5394 (save-buffer))
5395 ;; if modified, restore initial buffer
5396 (when (buffer-modified-p init-buf)
5397 (erase-buffer)
5398 (insert init-buf-string)
5399 (save-buffer)
5400 (goto-char init-point))
5401 output-file)))
5403 (defun markdown-export-and-preview ()
5404 "Export to XHTML using `markdown-export' and browse the resulting file."
5405 (interactive)
5406 (browse-url-of-file (markdown-export)))
5408 (defvar markdown-live-preview-buffer nil
5409 "Buffer used to preview markdown output in `markdown-live-preview-export'.")
5410 (make-variable-buffer-local 'markdown-live-preview-buffer)
5412 (defvar markdown-live-preview-source-buffer nil
5413 "Buffer with markdown source generating the source of the current
5414 buffer. Inverse of `markdown-live-preview-buffer'.")
5415 (make-variable-buffer-local 'markdown-live-preview-source-buffer)
5417 (defvar markdown-live-preview-currently-exporting nil)
5419 (defun markdown-live-preview-get-filename ()
5420 "Standardize the filename exported by `markdown-live-preview-export'."
5421 (markdown-export-file-name ".html"))
5423 (defun markdown-live-preview-window-eww (file)
5424 "A `markdown-live-preview-window-function' for previewing with eww."
5425 (if (require 'eww nil t)
5426 (progn
5427 (eww-open-file file)
5428 (get-buffer "*eww*"))
5429 (error "eww is not present or not loaded on this version of emacs")))
5431 (defun markdown-live-preview-window-serialize (buf)
5432 "Get window point and scroll data for all windows displaying BUF if BUF is
5433 non-nil."
5434 (when buf
5435 (mapcar (lambda (win) (list win (window-point win) (window-start win)))
5436 (get-buffer-window-list buf))))
5438 (defun markdown-live-preview-window-deserialize (window-posns)
5439 "Apply window point and scroll data from WINDOW-POSNS, given by
5440 `markdown-live-preview-window-serialize'."
5441 (cl-destructuring-bind (win pt start) window-posns
5442 (when (window-live-p win)
5443 (set-window-buffer win markdown-live-preview-buffer)
5444 (set-window-point win pt)
5445 (set-window-start win start))))
5447 (defun markdown-live-preview-export ()
5448 "Export to XHTML using `markdown-export' and browse the resulting file within
5449 Emacs using `markdown-live-preview-window-function' Return the buffer displaying
5450 the rendered output."
5451 (interactive)
5452 (let* ((markdown-live-preview-currently-exporting t)
5453 (cur-buf (current-buffer))
5454 (export-file (markdown-export (markdown-live-preview-get-filename)))
5455 ;; get positions in all windows currently displaying output buffer
5456 (window-data
5457 (markdown-live-preview-window-serialize
5458 markdown-live-preview-buffer)))
5459 (save-window-excursion
5460 (let ((output-buffer
5461 (funcall markdown-live-preview-window-function export-file)))
5462 (with-current-buffer output-buffer
5463 (setq markdown-live-preview-source-buffer cur-buf)
5464 (add-hook 'kill-buffer-hook
5465 #'markdown-live-preview-remove-on-kill t t))
5466 (with-current-buffer cur-buf
5467 (setq markdown-live-preview-buffer output-buffer))))
5468 (with-current-buffer cur-buf
5469 ;; reset all windows displaying output buffer to where they were,
5470 ;; now with the new output
5471 (mapc #'markdown-live-preview-window-deserialize window-data)
5472 ;; delete html editing buffer
5473 (let ((buf (get-file-buffer export-file))) (when buf (kill-buffer buf)))
5474 (when (and export-file (file-exists-p export-file)
5475 (eq markdown-live-preview-delete-export
5476 'delete-on-export))
5477 (delete-file export-file))
5478 markdown-live-preview-buffer)))
5480 (defun markdown-live-preview-remove ()
5481 (when (buffer-live-p markdown-live-preview-buffer)
5482 (kill-buffer markdown-live-preview-buffer))
5483 (setq markdown-live-preview-buffer nil)
5484 ;; if set to 'delete-on-export, the output has already been deleted
5485 (when (eq markdown-live-preview-delete-export 'delete-on-destroy)
5486 (let ((outfile-name (markdown-live-preview-get-filename)))
5487 (when (file-exists-p outfile-name)
5488 (delete-file outfile-name)))))
5490 (defun markdown-display-buffer-other-window (buf)
5491 (let ((cur-buf (current-buffer)))
5492 (switch-to-buffer-other-window buf)
5493 (set-buffer cur-buf)))
5495 (defun markdown-live-preview-if-markdown ()
5496 (when (and (derived-mode-p 'markdown-mode)
5497 markdown-live-preview-mode)
5498 (unless markdown-live-preview-currently-exporting
5499 (if (buffer-live-p markdown-live-preview-buffer)
5500 (markdown-live-preview-export)
5501 (markdown-display-buffer-other-window
5502 (markdown-live-preview-export))))))
5504 (defun markdown-live-preview-remove-on-kill ()
5505 (cond ((and (derived-mode-p 'markdown-mode)
5506 markdown-live-preview-mode)
5507 (markdown-live-preview-remove))
5508 (markdown-live-preview-source-buffer
5509 (with-current-buffer markdown-live-preview-source-buffer
5510 (setq markdown-live-preview-buffer nil))
5511 (setq markdown-live-preview-source-buffer nil))))
5513 (defun markdown-live-preview-switch-to-output ()
5514 (interactive)
5515 "Turn on `markdown-live-preview-mode' if not already on, and switch to its
5516 output buffer in another window."
5517 (if markdown-live-preview-mode
5518 (markdown-display-buffer-other-window (markdown-live-preview-export)))
5519 (markdown-live-preview-mode))
5521 (defun markdown-live-preview-re-export ()
5522 (interactive)
5523 "If the current buffer is a buffer displaying the exported version of a
5524 `markdown-live-preview-mode' buffer, call `markdown-live-preview-export' and
5525 update this buffer's contents."
5526 (when markdown-live-preview-source-buffer
5527 (with-current-buffer markdown-live-preview-source-buffer
5528 (markdown-live-preview-export))))
5530 (defun markdown-open ()
5531 "Open file for the current buffer with `markdown-open-command'."
5532 (interactive)
5533 (if (not markdown-open-command)
5534 (error "Variable `markdown-open-command' must be set")
5535 (if (not buffer-file-name)
5536 (error "Must be visiting a file")
5537 (call-process markdown-open-command
5538 nil nil nil buffer-file-name))))
5540 (defun markdown-kill-ring-save ()
5541 "Run Markdown on file and store output in the kill ring."
5542 (interactive)
5543 (save-window-excursion
5544 (markdown)
5545 (with-current-buffer markdown-output-buffer-name
5546 (kill-ring-save (point-min) (point-max)))))
5549 ;;; Links =====================================================================
5551 (defun markdown-link-p ()
5552 "Return non-nil when `point' is at a non-wiki link.
5553 See `markdown-wiki-link-p' for more information."
5554 (let ((case-fold-search nil))
5555 (and (not (markdown-wiki-link-p))
5556 (not (markdown-code-block-at-point))
5557 (or (thing-at-point-looking-at markdown-regex-link-inline)
5558 (thing-at-point-looking-at markdown-regex-link-reference)
5559 (thing-at-point-looking-at markdown-regex-uri)
5560 (thing-at-point-looking-at markdown-regex-angle-uri)))))
5562 (defun markdown-link-link ()
5563 "Return the link part of the regular (non-wiki) link at point.
5564 Works with both inline and reference style links. If point is
5565 not at a link or the link reference is not defined returns nil."
5566 (cond
5567 ((thing-at-point-looking-at markdown-regex-link-inline)
5568 (match-string-no-properties 6))
5569 ((thing-at-point-looking-at markdown-regex-link-reference)
5570 (let* ((text (match-string-no-properties 3))
5571 (reference (match-string-no-properties 6))
5572 (target (downcase (if (string= reference "") text reference))))
5573 (car (markdown-reference-definition target))))
5574 ((thing-at-point-looking-at markdown-regex-uri)
5575 (match-string-no-properties 0))
5576 ((thing-at-point-looking-at markdown-regex-angle-uri)
5577 (match-string-no-properties 2))
5578 (t nil)))
5580 (defun markdown-follow-link-at-point ()
5581 "Open the current non-wiki link in a browser."
5582 (interactive)
5583 (if (markdown-link-p) (browse-url (markdown-link-link))
5584 (error "Point is not at a Markdown link or URI")))
5587 ;;; WikiLink Following/Markup =================================================
5589 (defun markdown-wiki-link-p ()
5590 "Return non-nil when `point' is at a true wiki link.
5591 A true wiki link name matches `markdown-regex-wiki-link' but does not
5592 match the current file name after conversion. This modifies the data
5593 returned by `match-data'. Note that the potential wiki link name must
5594 be available via `match-string'."
5595 (let ((case-fold-search nil))
5596 (and (thing-at-point-looking-at markdown-regex-wiki-link)
5597 (not (markdown-code-block-at-point))
5598 (or (not buffer-file-name)
5599 (not (string-equal (buffer-file-name)
5600 (markdown-convert-wiki-link-to-filename
5601 (markdown-wiki-link-link))))))))
5603 (defun markdown-wiki-link-link ()
5604 "Return the link part of the wiki link using current match data.
5605 The location of the link component depends on the value of
5606 `markdown-wiki-link-alias-first'."
5607 (if markdown-wiki-link-alias-first
5608 (or (match-string-no-properties 5) (match-string-no-properties 3))
5609 (match-string-no-properties 3)))
5611 (defun markdown-wiki-link-alias ()
5612 "Return the alias or text part of the wiki link using current match data.
5613 The location of the alias component depends on the value of
5614 `markdown-wiki-link-alias-first'."
5615 (if markdown-wiki-link-alias-first
5616 (match-string-no-properties 3)
5617 (or (match-string-no-properties 5) (match-string-no-properties 3))))
5619 (defun markdown-convert-wiki-link-to-filename (name)
5620 "Generate a filename from the wiki link NAME.
5621 Spaces in NAME are replaced with `markdown-link-space-sub-char'.
5622 When in `gfm-mode', follow GitHub's conventions where [[Test Test]]
5623 and [[test test]] both map to Test-test.ext."
5624 (let ((basename (markdown-replace-regexp-in-string
5625 "[[:space:]\n]" markdown-link-space-sub-char name)))
5626 (when (eq major-mode 'gfm-mode)
5627 (setq basename (concat (upcase (substring basename 0 1))
5628 (downcase (substring basename 1 nil)))))
5629 (let* ((default
5630 (concat basename
5631 (if (and (buffer-file-name)
5632 (file-name-extension (buffer-file-name)))
5633 (concat "."
5634 (file-name-extension (buffer-file-name))))))
5635 (current default))
5636 (catch 'done
5637 (condition-case nil
5638 (cl-loop
5639 (if (or (not markdown-wiki-link-search-parent-directories)
5640 (file-exists-p current))
5641 (throw 'done current))
5642 (if (string-equal (expand-file-name current)
5643 (concat "/" default))
5644 (throw 'done default))
5645 (setq current (concat "../" current)))
5646 (error default))))))
5648 (defun markdown-follow-wiki-link (name &optional other)
5649 "Follow the wiki link NAME.
5650 Convert the name to a file name and call `find-file'. Ensure that
5651 the new buffer remains in `markdown-mode'. Open the link in another
5652 window when OTHER is non-nil."
5653 (let ((filename (markdown-convert-wiki-link-to-filename name))
5654 (wp (file-name-directory buffer-file-name)))
5655 (when other (other-window 1))
5656 (let ((default-directory wp))
5657 (find-file filename)))
5658 (when (not (eq major-mode 'markdown-mode))
5659 (markdown-mode)))
5661 (defun markdown-follow-wiki-link-at-point (&optional arg)
5662 "Find Wiki Link at point.
5663 With prefix argument ARG, open the file in other window.
5664 See `markdown-wiki-link-p' and `markdown-follow-wiki-link'."
5665 (interactive "P")
5666 (if (markdown-wiki-link-p)
5667 (markdown-follow-wiki-link (markdown-wiki-link-link) arg)
5668 (error "Point is not at a Wiki Link")))
5670 (defun markdown-highlight-wiki-link (from to face)
5671 "Highlight the wiki link in the region between FROM and TO using FACE."
5672 (put-text-property from to 'font-lock-face face))
5674 (defun markdown-unfontify-region-wiki-links (from to)
5675 "Remove wiki link faces from the region specified by FROM and TO."
5676 (interactive "*r")
5677 (remove-text-properties from to '(font-lock-face markdown-link-face))
5678 (remove-text-properties from to '(font-lock-face markdown-missing-link-face)))
5680 (defun markdown-fontify-region-wiki-links (from to)
5681 "Search region given by FROM and TO for wiki links and fontify them.
5682 If a wiki link is found check to see if the backing file exists
5683 and highlight accordingly."
5684 (goto-char from)
5685 (save-match-data
5686 (while (re-search-forward markdown-regex-wiki-link to t)
5687 (when (not (markdown-code-block-at-point))
5688 (let ((highlight-beginning (match-beginning 1))
5689 (highlight-end (match-end 1))
5690 (file-name
5691 (markdown-convert-wiki-link-to-filename
5692 (markdown-wiki-link-link))))
5693 (if (condition-case nil (file-exists-p file-name) (error nil))
5694 (markdown-highlight-wiki-link
5695 highlight-beginning highlight-end markdown-link-face)
5696 (markdown-highlight-wiki-link
5697 highlight-beginning highlight-end markdown-missing-link-face)))))))
5699 (defun markdown-extend-changed-region (from to)
5700 "Extend region given by FROM and TO so that we can fontify all links.
5701 The region is extended to the first newline before and the first
5702 newline after."
5703 ;; start looking for the first new line before 'from
5704 (goto-char from)
5705 (re-search-backward "\n" nil t)
5706 (let ((new-from (point-min))
5707 (new-to (point-max)))
5708 (if (not (= (point) from))
5709 (setq new-from (point)))
5710 ;; do the same thing for the first new line after 'to
5711 (goto-char to)
5712 (re-search-forward "\n" nil t)
5713 (if (not (= (point) to))
5714 (setq new-to (point)))
5715 (cl-values new-from new-to)))
5717 (defun markdown-check-change-for-wiki-link (from to)
5718 "Check region between FROM and TO for wiki links and re-fontify as needed."
5719 (interactive "*r")
5720 (let* ((modified (buffer-modified-p))
5721 (buffer-undo-list t)
5722 (inhibit-read-only t)
5723 (inhibit-point-motion-hooks t)
5724 deactivate-mark
5725 buffer-file-truename)
5726 (unwind-protect
5727 (save-excursion
5728 (save-match-data
5729 (save-restriction
5730 ;; Extend the region to fontify so that it starts
5731 ;; and ends at safe places.
5732 (cl-multiple-value-bind (new-from new-to)
5733 (markdown-extend-changed-region from to)
5734 (goto-char new-from)
5735 ;; Only refontify when the range contains text with a
5736 ;; wiki link face or if the wiki link regexp matches.
5737 (when (or (markdown-range-property-any
5738 new-from new-to 'font-lock-face
5739 (list markdown-link-face
5740 markdown-missing-link-face))
5741 (re-search-forward
5742 markdown-regex-wiki-link new-to t))
5743 ;; Unfontify existing fontification (start from scratch)
5744 (markdown-unfontify-region-wiki-links new-from new-to)
5745 ;; Now do the fontification.
5746 (markdown-fontify-region-wiki-links new-from new-to))))))
5747 (and (not modified)
5748 (buffer-modified-p)
5749 (set-buffer-modified-p nil)))))
5751 (defun markdown-check-change-for-wiki-link-after-change (from to _)
5752 "Check region between FROM and TO for wiki links and re-fontify as needed.
5753 Designed to be used with the `after-change-functions' hook."
5754 (markdown-check-change-for-wiki-link from to))
5756 (defun markdown-fontify-buffer-wiki-links ()
5757 "Refontify all wiki links in the buffer."
5758 (interactive)
5759 (markdown-check-change-for-wiki-link (point-min) (point-max)))
5762 ;;; Following and Jumping =====================================================
5764 (defun markdown-follow-thing-at-point (arg)
5765 "Follow thing at point if possible, such as a reference link or wiki link.
5766 Opens inline and reference links in a browser. Opens wiki links
5767 to other files in the current window, or the another window if
5768 ARG is non-nil.
5769 See `markdown-follow-link-at-point' and
5770 `markdown-follow-wiki-link-at-point'."
5771 (interactive "P")
5772 (cond ((markdown-link-p)
5773 (markdown-follow-link-at-point))
5774 ((markdown-wiki-link-p)
5775 (markdown-follow-wiki-link-at-point arg))
5777 (error "Nothing to follow at point"))))
5779 (defun markdown-jump ()
5780 "Jump to another location based on context at point.
5781 Jumps between reference links and definitions; between footnote
5782 markers and footnote text."
5783 (interactive)
5784 (cond ((markdown-footnote-text-positions)
5785 (markdown-footnote-return))
5786 ((markdown-footnote-marker-positions)
5787 (markdown-footnote-goto-text))
5788 ((thing-at-point-looking-at markdown-regex-link-reference)
5789 (markdown-reference-goto-definition))
5790 ((thing-at-point-looking-at markdown-regex-reference-definition)
5791 (markdown-reference-goto-link (match-string-no-properties 2)))
5793 (error "Nothing to jump to from context at point"))))
5796 ;;; Miscellaneous =============================================================
5798 (defun markdown-compress-whitespace-string (str)
5799 "Compress whitespace in STR and return result.
5800 Leading and trailing whitespace is removed. Sequences of multiple
5801 spaces, tabs, and newlines are replaced with single spaces."
5802 (markdown-replace-regexp-in-string "\\(^[ \t\n]+\\|[ \t\n]+$\\)" ""
5803 (markdown-replace-regexp-in-string "[ \t\n]+" " " str)))
5805 (defun markdown-line-number-at-pos (&optional pos)
5806 "Return (narrowed) buffer line number at position POS.
5807 If POS is nil, use current buffer location.
5808 This is an exact copy of `line-number-at-pos' for use in emacs21."
5809 (let ((opoint (or pos (point))) start)
5810 (save-excursion
5811 (goto-char (point-min))
5812 (setq start (point))
5813 (goto-char opoint)
5814 (forward-line 0)
5815 (1+ (count-lines start (point))))))
5817 (defun markdown-inside-link-text-p ()
5818 "Return nil if not currently within link anchor text."
5819 (looking-back "\\[[^]]*" nil))
5821 (defun markdown-line-is-reference-definition-p ()
5822 "Return whether the current line is a (non-footnote) reference defition."
5823 (save-excursion
5824 (move-beginning-of-line 1)
5825 (and (looking-at-p markdown-regex-reference-definition)
5826 (not (looking-at-p "[ \t]*\\[^")))))
5828 (defun markdown-adaptive-fill-function ()
5829 "Return prefix for filling paragraph or nil if not determined."
5830 (cond
5831 ;; List item inside blockquote
5832 ((looking-at "^[ \t]*>[ \t]*\\(\\(?:[0-9]+\\|#\\)\\.\\|[*+-]\\)[ \t]+")
5833 (markdown-replace-regexp-in-string
5834 "[0-9\\.*+-]" " " (match-string-no-properties 0)))
5835 ;; Blockquote
5836 ((looking-at "^[ \t]*>[ \t]*")
5837 (match-string-no-properties 0))
5838 ;; List items
5839 ((looking-at markdown-regex-list)
5840 (match-string-no-properties 0))
5841 ((looking-at markdown-regex-footnote-definition)
5842 " ") ; four spaces
5843 ;; No match
5844 (t nil)))
5846 (defun markdown-fill-forward-paragraph-function (&optional arg)
5847 (let* ((arg (or arg 1))
5848 (paragraphs-remaining (forward-paragraph arg))
5849 (start (point)))
5850 (when (< arg 0)
5851 (while (and (not (eobp))
5852 (progn (move-to-left-margin) (not (eobp)))
5853 (looking-at paragraph-separate))
5854 (forward-line 1))
5855 (if (looking-at markdown-regex-list)
5856 (forward-char (length (match-string 0)))
5857 (goto-char start)))
5858 paragraphs-remaining))
5861 ;;; Extensions ================================================================
5863 (defun markdown-reload-extensions ()
5864 "Check settings, update font-lock keywords, and re-fontify buffer."
5865 (interactive)
5866 (when (eq major-mode 'markdown-mode)
5867 (setq markdown-mode-font-lock-keywords
5868 (append
5869 markdown-mode-font-lock-keywords-basic
5870 (when markdown-enable-math
5871 markdown-mode-font-lock-keywords-math)))
5872 (setq font-lock-defaults
5873 '(markdown-mode-font-lock-keywords
5874 nil nil nil nil
5875 (font-lock-syntactic-face-function . markdown-syntactic-face)))
5876 (when (fboundp 'font-lock-refresh-defaults) (font-lock-refresh-defaults))))
5878 (defun markdown-enable-math (&optional arg)
5879 "Toggle support for inline and display LaTeX math expressions.
5880 With a prefix argument ARG, enable math mode if ARG is positive,
5881 and disable it otherwise. If called from Lisp, enable the mode
5882 if ARG is omitted or nil."
5883 (interactive (list (or current-prefix-arg 'toggle)))
5884 (setq markdown-enable-math
5885 (if (eq arg 'toggle)
5886 (not markdown-enable-math)
5887 (> (prefix-numeric-value arg) 0)))
5888 (if markdown-enable-math
5889 (message "markdown-mode math support enabled")
5890 (message "markdown-mode math support disabled"))
5891 (markdown-reload-extensions))
5893 (defun markdown-handle-local-variables ()
5894 "Runs as a `hack-local-variables-hook' to update font lock rules.
5895 Checks to see if there is actually a markdown-mode file local variable
5896 before regenerating font-lock rules for extensions."
5897 (when (and (boundp 'file-local-variables-alist)
5898 (assoc 'markdown-enable-math file-local-variables-alist))
5899 (markdown-reload-extensions)))
5902 ;;; GFM Checkboxes as Buttons =================================================
5904 (require 'button)
5906 (define-button-type 'markdown-gfm-checkbox-button
5907 'follow-link t
5908 'face 'markdown-gfm-checkbox-face
5909 'mouse-face 'markdown-highlight-face
5910 'action #'markdown-toggle-gfm-checkbox)
5912 (defun markdown-toggle-gfm-checkbox (button)
5913 "Toggle a GFM checkbox clicked on."
5914 (save-match-data
5915 (save-excursion
5916 (goto-char (button-start button))
5917 (cond ((looking-at "\\[ \\]")
5918 (replace-match "[x]" nil t))
5919 ((looking-at "\\[[xX]\\]")
5920 (replace-match "[ ]" nil t))))))
5922 (defun markdown-make-gfm-checkboxes-buttons (start end)
5923 "Make GFM checkboxes buttons in region between START and END."
5924 (save-excursion
5925 (goto-char start)
5926 (let ((case-fold-search t))
5927 (save-excursion
5928 (while (re-search-forward markdown-regex-gfm-checkbox end t)
5929 (make-button (match-beginning 1) (match-end 1)
5930 :type 'markdown-gfm-checkbox-button))))))
5932 ;; Called when any modification is made to buffer text.
5933 (defun markdown-gfm-checkbox-after-change-function (beg end old-len)
5934 "Add to `after-change-functions' to setup GFM checkboxes as buttons."
5935 (save-excursion
5936 (save-match-data
5937 ;; Rescan between start of line from `beg' and start of line after `end'.
5938 (markdown-make-gfm-checkboxes-buttons
5939 (progn (goto-char beg) (beginning-of-line) (point))
5940 (progn (goto-char end) (forward-line 1) (point))))))
5943 ;;; Mode Definition ==========================================================
5945 (defun markdown-show-version ()
5946 "Show the version number in the minibuffer."
5947 (interactive)
5948 (message "markdown-mode, version %s" markdown-mode-version))
5950 ;;;###autoload
5951 (define-derived-mode markdown-mode text-mode "Markdown"
5952 "Major mode for editing Markdown files."
5953 ;; Natural Markdown tab width
5954 (setq tab-width 4)
5955 ;; Comments
5956 (make-local-variable 'comment-start)
5957 (setq comment-start "<!-- ")
5958 (make-local-variable 'comment-end)
5959 (setq comment-end " -->")
5960 (make-local-variable 'comment-start-skip)
5961 (setq comment-start-skip "<!--[ \t]*")
5962 (make-local-variable 'comment-column)
5963 (setq comment-column 0)
5964 (set (make-local-variable 'comment-auto-fill-only-comments) nil)
5965 ;; Syntax
5966 (add-hook 'syntax-propertize-extend-region-functions
5967 'markdown-syntax-propertize-extend-region)
5968 (set (make-local-variable 'syntax-propertize-function)
5969 'markdown-syntax-propertize)
5970 ;; Font lock.
5971 (set (make-local-variable 'markdown-mode-font-lock-keywords) nil)
5972 (set (make-local-variable 'font-lock-defaults) nil)
5973 (set (make-local-variable 'font-lock-multiline) t)
5974 ;; Extensions
5975 (make-local-variable 'markdown-enable-math)
5976 ;; Reload extensions
5977 (markdown-reload-extensions)
5978 ;; Add a buffer-local hook to reload after file-local variables are read
5979 (add-hook 'hack-local-variables-hook 'markdown-handle-local-variables nil t)
5980 ;; For imenu support
5981 (setq imenu-create-index-function
5982 (if markdown-nested-imenu-heading-index
5983 'markdown-imenu-create-nested-index
5984 'markdown-imenu-create-flat-index))
5985 ;; For menu support in XEmacs
5986 (easy-menu-add markdown-mode-menu markdown-mode-map)
5987 ;; Defun movement
5988 (set (make-local-variable 'beginning-of-defun-function)
5989 'markdown-beginning-of-defun)
5990 (set (make-local-variable 'end-of-defun-function)
5991 'markdown-end-of-defun)
5992 ;; Paragraph filling
5993 (set
5994 ; Should match start of lines that start or separate paragraphs
5995 (make-local-variable 'paragraph-start)
5996 (mapconcat 'identity
5998 "\f" ; starts with a literal line-feed
5999 "[ \t\f]*$" ; space-only line
6000 "[ \t]*[*+-][ \t]+" ; unordered list item
6001 "[ \t]*\\(?:[0-9]+\\|#\\)\\.[ \t]+" ; ordered list item
6002 "[ \t]*\\[\\S-*\\]:[ \t]+" ; link ref def
6003 "[ \t]*:[ \t]+" ; definition
6005 "\\|"))
6006 (set
6007 ; Should match lines that separate paragraphs without being
6008 ; part of any paragraph:
6009 (make-local-variable 'paragraph-separate)
6010 (mapconcat 'identity
6011 '("[ \t\f]*$" ; space-only line
6012 ; The following is not ideal, but the Fill customization
6013 ; options really only handle paragraph-starting prefixes,
6014 ; not paragraph-ending suffixes:
6015 ".* $" ; line ending in two spaces
6016 "[ \t]*\\[\\^\\S-*\\]:[ \t]*$") ; just the start of a footnote def
6017 "\\|"))
6018 (set (make-local-variable 'adaptive-fill-first-line-regexp)
6019 "\\`[ \t]*>[ \t]*?\\'")
6020 (set (make-local-variable 'adaptive-fill-regexp) "\\s-*")
6021 (set (make-local-variable 'adaptive-fill-function)
6022 'markdown-adaptive-fill-function)
6023 (set (make-local-variable 'fill-forward-paragraph-function)
6024 'markdown-fill-forward-paragraph-function)
6025 ;; Outline mode
6026 (make-local-variable 'outline-regexp)
6027 (setq outline-regexp markdown-regex-header)
6028 (make-local-variable 'outline-level)
6029 (setq outline-level 'markdown-outline-level)
6030 ;; Cause use of ellipses for invisible text.
6031 (add-to-invisibility-spec '(outline . t))
6033 ;; Inhibiting line-breaking:
6034 ;; Separating out each condition into a separate function so that users can
6035 ;; override if desired (with remove-hook)
6036 (add-hook 'fill-nobreak-predicate
6037 'markdown-inside-link-text-p nil t)
6038 (add-hook 'fill-nobreak-predicate
6039 'markdown-line-is-reference-definition-p nil t)
6041 ;; Indentation
6042 (setq indent-line-function markdown-indent-function)
6044 ;; Backwards compatibility with markdown-css-path
6045 (when (boundp 'markdown-css-path)
6046 (warn "markdown-css-path is deprecated, see markdown-css-paths.")
6047 (add-to-list 'markdown-css-paths markdown-css-path))
6049 ;; Prepare hooks for XEmacs compatibility
6050 (when (featurep 'xemacs)
6051 (make-local-hook 'after-change-functions)
6052 (make-local-hook 'font-lock-extend-region-functions)
6053 (make-local-hook 'window-configuration-change-hook))
6055 ;; Anytime text changes make sure it gets fontified correctly
6056 (add-hook 'after-change-functions
6057 'markdown-check-change-for-wiki-link-after-change t t)
6059 ;; Make checkboxes buttons
6060 (when markdown-make-gfm-checkboxes-buttons
6061 (markdown-make-gfm-checkboxes-buttons (point-min) (point-max))
6062 (add-hook 'after-change-functions 'markdown-gfm-checkbox-after-change-function t t))
6064 ;; If we left the buffer there is a really good chance we were
6065 ;; creating one of the wiki link documents. Make sure we get
6066 ;; refontified when we come back.
6067 (add-hook 'window-configuration-change-hook
6068 'markdown-fontify-buffer-wiki-links t t)
6070 ;; add live preview export hook
6071 (add-hook 'after-save-hook #'markdown-live-preview-if-markdown t t)
6072 (add-hook 'kill-buffer-hook #'markdown-live-preview-remove-on-kill t t)
6074 ;; do the initial link fontification
6075 (markdown-fontify-buffer-wiki-links))
6077 ;;;###autoload
6078 (add-to-list 'auto-mode-alist '("\\.markdown\\'" . markdown-mode))
6079 ;;;###autoload
6080 (add-to-list 'auto-mode-alist '("\\.text\\'" . markdown-mode))
6081 ;;;###autoload
6082 (add-to-list 'auto-mode-alist '("\\.md\\'" . markdown-mode))
6085 ;;; GitHub Flavored Markdown Mode ============================================
6087 (defvar gfm-mode-hook nil
6088 "Hook run when entering GFM mode.")
6090 (defvar gfm-font-lock-keywords
6091 (append
6092 ;; GFM features to match first
6093 (list
6094 (cons markdown-regex-strike-through '((3 markdown-markup-face)
6095 (4 markdown-strike-through-face)
6096 (5 markdown-markup-face))))
6097 ;; Basic Markdown features (excluding possibly overridden ones)
6098 markdown-mode-font-lock-keywords-basic)
6099 "Default highlighting expressions for GitHub Flavored Markdown mode.")
6101 ;;;###autoload
6102 (define-derived-mode gfm-mode markdown-mode "GFM"
6103 "Major mode for editing GitHub Flavored Markdown files."
6104 (setq markdown-link-space-sub-char "-")
6105 (set (make-local-variable 'font-lock-defaults)
6106 '(gfm-font-lock-keywords))
6107 ;; do the initial link fontification
6108 (markdown-fontify-buffer-wiki-links)
6109 (markdown-gfm-parse-buffer-for-languages))
6112 ;;; Live Preview Mode ============================================
6113 (define-minor-mode markdown-live-preview-mode
6114 "Toggle native previewing on save for a specific markdown file."
6115 :lighter " MD-Preview"
6116 (if markdown-live-preview-mode
6117 (markdown-display-buffer-other-window (markdown-live-preview-export))
6118 (markdown-live-preview-remove)))
6121 (provide 'markdown-mode)
6122 ;; Local Variables:
6123 ;; indent-tabs-mode: nil
6124 ;; End:
6125 ;;; markdown-mode.el ends here