Fixed bug introduced while adding feature
[schreib.git] / schreib-markdown-mode.el
1 ;;; dislines-markdown-mode.el --- Emacs Major mode for multilingual
2 ;;; markdown-formatted text files using dislines.
3
4 ;; Copyright (C) 2007-2014 Jason R. Blevins <jrblevin@sdf.org>
5 ;; Copyright (C) 2007, 2009 Edward O'Connor <ted@oconnor.cx>
6 ;; Copyright (C) 2007 Conal Elliott <conal@conal.net>
7 ;; Copyright (C) 2008 Greg Bognar <greg_bognar@hms.harvard.edu>
8 ;; Copyright (C) 2008 Dmitry Dzhus <mail@sphinx.net.ru>
9 ;; Copyright (C) 2008 Bryan Kyle <bryan.kyle@gmail.com>
10 ;; Copyright (C) 2008 Ben Voui <intrigeri@boum.org>
11 ;; Copyright (C) 2009 Ankit Solanki <ankit.solanki@gmail.com>
12 ;; Copyright (C) 2009 Hilko Bengen <bengen@debian.org>
13 ;; Copyright (C) 2009 Peter Williams <pezra@barelyenough.org>
14 ;; Copyright (C) 2010 George Ogata <george.ogata@gmail.com>
15 ;; Copyright (C) 2011 Eric Merritt <ericbmerritt@gmail.com>
16 ;; Copyright (C) 2011 Philippe Ivaldi <pivaldi@sfr.fr>
17 ;; Copyright (C) 2011 Jeremiah Dodds <jeremiah.dodds@gmail.com>
18 ;; Copyright (C) 2011 Christopher J. Madsen <cjm@cjmweb.net>
19 ;; Copyright (C) 2011 Shigeru Fukaya <shigeru.fukaya@gmail.com>
20 ;; Copyright (C) 2011 Joost Kremers <joostkremers@fastmail.fm>
21 ;; Copyright (C) 2011-2012 Donald Ephraim Curtis <dcurtis@milkbox.net>
22 ;; Copyright (C) 2012 Akinori Musha <knu@idaemons.org>
23 ;; Copyright (C) 2012 Zhenlei Jia <zhenlei.jia@gmail.com>
24 ;; Copyright (C) 2012 Peter Jones <pjones@pmade.com>
25 ;; Copyright (C) 2013 Matus Goljer <dota.keys@gmail.com>
26 ;; Copyright (C) 2016 Gabriel PĂ©rez-Cerezo <gabriel@gpcf.eu> (D353EC69)
27
28 ;; Author: Jason R. Blevins <jrblevin@sdf.org>
29 ;; Maintainer: Jason R. Blevins <jrblevin@sdf.org>
30 ;; Created: May 24, 2007
31 ;; Version: 2.0
32 ;; Keywords: Markdown, GitHub Flavored Markdown, itex
33 ;; URL: http://jblevins.org/projects/markdown-mode/
34
35 ;; This file is not part of GNU Emacs.
36
37 ;; This program is free software; you can redistribute it and/or modify
38 ;; it under the terms of the GNU General Public License as published by
39 ;; the Free Software Foundation; either version 2, or (at your option)
40 ;; any later version.
41
42 ;; This program is distributed in the hope that it will be useful,
43 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
44 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
45 ;; GNU General Public License for more details.
46
47 ;; You should have received a copy of the GNU General Public License
48 ;; along with this program; if not, write to the Free Software
49 ;; Foundation, Inc., 51 Franklin Street, Fifth Floor,
50 ;; Boston, MA 02110-1301, USA.
51
52 ;;; Commentary:
53
54 ;; markdown-mode is a major mode for editing [Markdown][]-formatted
55 ;; text files in GNU Emacs. markdown-mode is free software, licensed
56 ;; under the GNU GPL.
57 ;;
58 ;; [Markdown]: http://daringfireball.net/projects/markdown/
59 ;;
60 ;; The latest stable version is markdown-mode 2.0, released on March 24, 2013:
61 ;;
62 ;; * [markdown-mode.el][]
63 ;; * [Screenshot][][^theme]
64 ;; * [Release notes][]
65 ;;
66 ;; [markdown-mode.el]: http://jblevins.org/projects/markdown-mode/markdown-mode.el
67 ;; [screenshot]: http://jblevins.org/projects/markdown-mode/screenshots/20130131-002.png
68 ;; [release notes]: http://jblevins.org/projects/markdown-mode/rev-2-0
69 ;;
70 ;; [^theme]: The theme used in the screenshot is
71 ;; [color-theme-twilight](https://github.com/crafterm/twilight-emacs).
72 ;;
73 ;; markdown-mode is also available in several package managers, including:
74 ;;
75 ;; * Debian and Ubuntu Linux: [emacs-goodies-el][]
76 ;; * RedHat and Fedora Linux: [emacs-goodies][]
77 ;; * NetBSD: [textproc/markdown-mode][]
78 ;; * Arch Linux (AUR): [emacs-markdown-mode-git][]
79 ;; * MacPorts: [markdown-mode.el][macports-package] ([pending][macports-ticket])
80 ;; * FreeBSD: [textproc/markdown-mode.el][freebsd-port]
81 ;;
82 ;; [emacs-goodies-el]: http://packages.debian.org/emacs-goodies-el
83 ;; [emacs-goodies]: https://admin.fedoraproject.org/pkgdb/acls/name/emacs-goodies
84 ;; [textproc/markdown-mode]: http://pkgsrc.se/textproc/markdown-mode
85 ;; [emacs-markdown-mode-git]: http://aur.archlinux.org/packages.php?ID=30389
86 ;; [macports-package]: https://trac.macports.org/browser/trunk/dports/editors/markdown-mode.el/Portfile
87 ;; [macports-ticket]: http://trac.macports.org/ticket/35716
88 ;; [freebsd-port]: http://svnweb.freebsd.org/ports/head/textproc/markdown-mode.el
89 ;;
90 ;; The latest development version can be downloaded directly
91 ;; ([markdown-mode.el][devel.el]) or it can be obtained from the
92 ;; (browsable and clonable) Git repository at
93 ;; <http://jblevins.org/git/markdown-mode.git>. The entire repository,
94 ;; including the full project history, can be cloned via the Git protocol
95 ;; by running
96 ;;
97 ;; git clone git://jblevins.org/git/markdown-mode.git
98 ;;
99 ;; [devel.el]: http://jblevins.org/git/markdown-mode.git/plain/markdown-mode.el
100
101 ;;; Installation:
102
103 ;; Make sure to place `markdown-mode.el` somewhere in the load-path and add
104 ;; the following lines to your `.emacs` file to associate markdown-mode
105 ;; with `.text`, `.markdown`, and `.md` files:
106 ;;
107 ;; (autoload 'markdown-mode "markdown-mode"
108 ;; "Major mode for editing Markdown files" t)
109 ;; (add-to-list 'auto-mode-alist '("\\.text\\'" . markdown-mode))
110 ;; (add-to-list 'auto-mode-alist '("\\.markdown\\'" . markdown-mode))
111 ;; (add-to-list 'auto-mode-alist '("\\.md\\'" . markdown-mode))
112 ;;
113 ;; There is no official Markdown file extension, nor is there even a
114 ;; _de facto_ standard, so you can easily add, change, or remove any
115 ;; of the file extensions above as needed.
116
117 ;;; Usage:
118
119 ;; Keybindings are grouped by prefixes based on their function. For
120 ;; example, the commands for inserting links are grouped under `C-c
121 ;; C-a`, where the `C-a` is a mnemonic for the HTML `<a>` tag. In
122 ;; other cases, the connection to HTML is not direct. For example,
123 ;; commands dealing with headings begin with `C-c C-t` (mnemonic:
124 ;; titling). The primary commands in each group will are described
125 ;; below. You can obtain a list of all keybindings by pressing `C-c
126 ;; C-h`. Movement and shifting commands tend to be associated with
127 ;; paired delimiters such as `M-{` and `M-}` or `C-c <` and `C-c >`.
128 ;; Outline navigation keybindings the same as in `org-mode'. Finally,
129 ;; commands for running Markdown or doing maintenance on an open file
130 ;; are grouped under the `C-c C-c` prefix. The most commonly used
131 ;; commands are described below. You can obtain a list of all
132 ;; keybindings by pressing `C-c C-h`.
133 ;;
134 ;; * Hyperlinks: `C-c C-a`
135 ;;
136 ;; In this group, `C-c C-a l` inserts an inline link of the form
137 ;; `[text](url)`. The link text is determined as follows. First,
138 ;; if there is an active region (i.e., when transient mark mode is
139 ;; on and the mark is active), use it as the link text. Second,
140 ;; if the point is at a word, use that word as the link text. In
141 ;; these two cases, the original text will be replaced with the
142 ;; link and point will be left at the position for inserting a
143 ;; URL. Otherwise, insert empty link markup and place the point
144 ;; for inserting the link text.
145 ;;
146 ;; `C-c C-a L` inserts a reference link of the form `[text][label]`
147 ;; and, optionally, a corresponding reference label definition.
148 ;; The link text is determined in the same way as with an inline
149 ;; link (using the region, when active, or the word at the point),
150 ;; but instead of inserting empty markup as a last resort, the
151 ;; link text will be read from the minibuffer. The reference
152 ;; label will be read from the minibuffer in both cases, with
153 ;; completion from the set of currently defined references. To
154 ;; create an implicit reference link, press `RET` to accept the
155 ;; default, an empty label. If the entered referenced label is
156 ;; not defined, additionally prompt for the URL and (optional)
157 ;; title. If a URL is provided, a reference definition will be
158 ;; inserted in accordance with `markdown-reference-location'.
159 ;; If a title is given, it will be added to the end of the
160 ;; reference definition and will be used to populate the title
161 ;; attribute when converted to XHTML.
162 ;;
163 ;; `C-c C-a u` inserts a bare url, delimited by angle brackets. When
164 ;; there is an active region, the text in the region is used as the
165 ;; URL. If the point is at a URL, that url is used. Otherwise,
166 ;; insert angle brackets and position the point in between them
167 ;; for inserting the URL.
168 ;;
169 ;; `C-c C-a f` inserts a footnote marker at the point, inserts a
170 ;; footnote definition below, and positions the point for
171 ;; inserting the footnote text. Note that footnotes are an
172 ;; extension to Markdown and are not supported by all processors.
173 ;;
174 ;; `C-c C-a w` behaves much like the inline link insertion command
175 ;; and inserts a wiki link of the form `[[WikiLink]]`. If there
176 ;; is an active region, use the region as the link text. If the
177 ;; point is at a word, use the word as the link text. If there is
178 ;; no active region and the point is not at word, simply insert
179 ;; link markup. Note that wiki links are an extension to Markdown
180 ;; and are not supported by all processors.
181 ;;
182 ;; * Images: `C-c C-i`
183 ;;
184 ;; `C-c C-i i` inserts markup for an inline image, using the
185 ;; active region or the word at point, if any, as the alt text.
186 ;; `C-c C-i I` behaves similarly and inserts a reference-style
187 ;; image.
188 ;;
189 ;; * Styles: `C-c C-s`
190 ;;
191 ;; `C-c C-s e` inserts markup to make a region or word italic (`e`
192 ;; for `<em>` or emphasis). If there is an active region, make
193 ;; the region italic. If the point is at a non-italic word, make
194 ;; the word italic. If the point is at an italic word or phrase,
195 ;; remove the italic markup. Otherwise, simply insert italic
196 ;; delimiters and place the cursor in between them. Similarly,
197 ;; use `C-c C-s s` for bold (`<strong>`) and `C-c C-s c` for
198 ;; inline code (`<code>`).
199 ;;
200 ;; `C-c C-s b` inserts a blockquote using the active region, if any,
201 ;; or starts a new blockquote. `C-c C-s C-b` is a variation which
202 ;; always operates on the region, regardless of whether it is
203 ;; active or not. The appropriate amount of indentation, if any,
204 ;; is calculated automatically given the surrounding context, but
205 ;; may be adjusted later using the region indentation commands.
206 ;;
207 ;; `C-c C-s p` behaves similarly for inserting preformatted code
208 ;; blocks, with `C-c C-s C-p` being the region-only counterpart.
209 ;;
210 ;; * Headings: `C-c C-t`
211 ;;
212 ;; All heading insertion commands use the text in the active
213 ;; region, if any, as the heading text. Otherwise, if the current
214 ;; line is not blank, they use the text on the current line.
215 ;; Finally, the setext commands will prompt for heading text if
216 ;; there is no active region and the current line is blank.
217 ;;
218 ;; `C-c C-t h` inserts a heading with automatically chosen type and
219 ;; level (both determined by the previous heading). `C-c C-t H`
220 ;; behaves similarly, but uses setext (underlined) headings when
221 ;; possible, still calculating the level automatically.
222 ;; In cases where the automatically-determined level is not what
223 ;; you intended, the level can be quickly promoted or demoted
224 ;; (as described below). Alternatively, a `C-u` prefix can be
225 ;; given to insert a heading promoted by one level or a `C-u C-u`
226 ;; prefix can be given to insert a heading demoted by one level.
227 ;;
228 ;; To insert a heading of a specific level and type, use `C-c C-t 1`
229 ;; through `C-c C-t 6` for atx (hash mark) headings and `C-c C-t !` or
230 ;; `C-c C-t @` for setext headings of level one or two, respectively.
231 ;; Note that `!` is `S-1` and `@` is `S-2`.
232 ;;
233 ;; If the point is at a heading, these commands will replace the
234 ;; existing markup in order to update the level and/or type of the
235 ;; heading. To remove the markup of the heading at the point,
236 ;; press `C-c C-k` to kill the heading and press `C-y` to yank the
237 ;; heading text back into the buffer.
238 ;;
239 ;; * Horizontal Rules: `C-c -`
240 ;;
241 ;; `C-c -` inserts a horizontal rule. By default, insert the
242 ;; first string in the list `markdown-hr-strings' (the most
243 ;; prominent rule). With a `C-u` prefix, insert the last string.
244 ;; With a numeric prefix `N`, insert the string in position `N`
245 ;; (counting from 1).
246 ;;
247 ;; * Markdown and Maintenance Commands: `C-c C-c`
248 ;;
249 ;; *Compile:* `C-c C-c m` will run Markdown on the current buffer
250 ;; and show the output in another buffer. *Preview*: `C-c C-c p`
251 ;; runs Markdown on the current buffer and previews, stores the
252 ;; output in a temporary file, and displays the file in a browser.
253 ;; *Export:* `C-c C-c e` will run Markdown on the current buffer
254 ;; and save the result in the file `basename.html`, where
255 ;; `basename` is the name of the Markdown file with the extension
256 ;; removed. *Export and View:* press `C-c C-c v` to export the
257 ;; file and view it in a browser. **For both export commands, the
258 ;; output file will be overwritten without notice.**
259 ;; *Open:* `C-c C-c o` will open the Markdown source file directly
260 ;; using `markdown-open-command'.
261 ;;
262 ;; To summarize:
263 ;;
264 ;; - `C-c C-c m`: `markdown-command' > `*markdown-output*` buffer.
265 ;; - `C-c C-c p`: `markdown-command' > temporary file > browser.
266 ;; - `C-c C-c e`: `markdown-command' > `basename.html`.
267 ;; - `C-c C-c v`: `markdown-command' > `basename.html` > browser.
268 ;; - `C-c C-c w`: `markdown-command' > kill ring.
269 ;; - `C-c C-c o`: `markdown-open-command'.
270 ;;
271 ;; `C-c C-c c` will check for undefined references. If there are
272 ;; any, a small buffer will open with a list of undefined
273 ;; references and the line numbers on which they appear. In Emacs
274 ;; 22 and greater, selecting a reference from this list and
275 ;; pressing `RET` will insert an empty reference definition at the
276 ;; end of the buffer. Similarly, selecting the line number will
277 ;; jump to the corresponding line.
278 ;;
279 ;; `C-c C-c n` renumbers any ordered lists in the buffer that are
280 ;; out of sequence.
281 ;;
282 ;; `C-c C-c ]` completes all headings and normalizes all horizontal
283 ;; rules in the buffer.
284 ;;
285 ;; * Following Links: `C-c C-o`
286 ;;
287 ;; Press `C-c C-o` when the point is on an inline or reference
288 ;; link to open the URL in a browser. When the point is at a
289 ;; wiki link, open it in another buffer (in the current window,
290 ;; or in the other window with the `C-u` prefix). Use `M-p` and
291 ;; `M-n` to quickly jump to the previous or next link of any type.
292 ;;
293 ;; * Jumping: `C-c C-j`
294 ;;
295 ;; Use `C-c C-j` to jump from the object at point to its counterpart
296 ;; elsewhere in the text, when possible. Jumps between reference
297 ;; links and definitions; between footnote markers and footnote
298 ;; text. If more than one link uses the same reference name, a
299 ;; new buffer will be created containing clickable buttons for jumping
300 ;; to each link. You may press `TAB` or `S-TAB` to jump between
301 ;; buttons in this window.
302 ;;
303 ;; * Promotion and Demotion: `C-c C--` and `C-c C-=`
304 ;;
305 ;; Headings, horizontal rules, and list items can be promoted and
306 ;; demoted, as well as bold and italic text. For headings,
307 ;; "promotion" means *decreasing* the level (i.e., moving from
308 ;; `<h2>` to `<h1>`) while "demotion" means *increasing* the
309 ;; level. For horizontal rules, promotion and demotion means
310 ;; moving backward or forward through the list of rule strings in
311 ;; `markdown-hr-strings'. For bold and italic text, promotion and
312 ;; demotion means changing the markup from underscores to asterisks.
313 ;; Press `C-c C--` or `M-LEFT` to promote the element at the point
314 ;; if possible.
315 ;;
316 ;; To remember these commands, note that `-` is for decreasing the
317 ;; level (promoting), and `=` (on the same key as `+`) is for
318 ;; increasing the level (demoting). Similarly, the left and right
319 ;; arrow keys indicate the direction that the atx heading markup
320 ;; is moving in when promoting or demoting.
321 ;;
322 ;; * Completion: `C-c C-]`
323 ;;
324 ;; Complete markup is in normalized form, which means, for
325 ;; example, that the underline portion of a setext header is the
326 ;; same length as the heading text, or that the number of leading
327 ;; and trailing hash marks of an atx header are equal and that
328 ;; there is no extra whitespace in the header text. `C-c C-]`
329 ;; completes the markup at the point, if it is determined to be
330 ;; incomplete.
331 ;;
332 ;; * Editing Lists: `M-RET`, `M-UP`, `M-DOWN`, `M-LEFT`, and `M-RIGHT`
333 ;;
334 ;; New list items can be inserted with `M-RET`. This command
335 ;; determines the appropriate marker (one of the possible
336 ;; unordered list markers or the next number in sequence for an
337 ;; ordered list) and indentation level by examining nearby list
338 ;; items. If there is no list before or after the point, start a
339 ;; new list. Prefix this command by `C-u` to decrease the
340 ;; indentation by one level. Prefix this command by `C-u C-u` to
341 ;; increase the indentation by one level.
342 ;;
343 ;; Existing list items can be moved up or down with `M-UP` or
344 ;; `M-DOWN` and indented or exdented with `M-RIGHT` or `M-LEFT`.
345 ;;
346 ;; * Shifting the Region: `C-c <` and `C-c >`
347 ;;
348 ;; Text in the region can be indented or exdented as a group using
349 ;; `C-c >` to indent to the next indentation point (calculated in
350 ;; the current context), and `C-c <` to exdent to the previous
351 ;; indentation point. These keybindings are the same as those for
352 ;; similar commands in `python-mode'.
353 ;;
354 ;; * Killing Elements: `C-c C-k`
355 ;;
356 ;; Press `C-c C-k` to kill the thing at point and add important
357 ;; text, without markup, to the kill ring. Possible things to
358 ;; kill include (roughly in order of precedece): inline code,
359 ;; headings, horizonal rules, links (add link text to kill ring),
360 ;; images (add alt text to kill ring), angle URIs, email
361 ;; addresses, bold, italics, reference definitions (add URI to
362 ;; kill ring), footnote markers and text (kill both marker and
363 ;; text, add text to kill ring), and list items.
364 ;;
365 ;; * Outline Navigation: `C-c C-n`, `C-c C-p`, `C-c C-f`, `C-c C-b`, and `C-c C-u`
366 ;;
367 ;; Navigation between headings is possible using `outline-mode'.
368 ;; Use `C-c C-n` and `C-c C-p` to move between the next and previous
369 ;; visible headings. Similarly, `C-c C-f` and `C-c C-b` move to the
370 ;; next and previous visible headings at the same level as the one
371 ;; at the point. Finally, `C-c C-u` will move up to a lower-level
372 ;; (higher precedence) visible heading.
373 ;;
374 ;; * Movement by Paragraph or Block: `M-{` and `M-}`
375 ;;
376 ;; The definition of a "paragraph" is slightly different in
377 ;; markdown-mode than, say, text-mode, because markdown-mode
378 ;; supports filling for list items and respects hard line breaks,
379 ;; both of which break paragraphs. So, markdown-mode overrides
380 ;; the usual paragraph navigation commands `M-{` and `M-}` so that
381 ;; with a `C-u` prefix, these commands jump to the beginning or
382 ;; end of an entire block of text, respectively, where "blocks"
383 ;; are separated by one or more lines.
384 ;;
385 ;; * Movement by Defun: `C-M-a`, `C-M-e`, and `C-M-h`
386 ;;
387 ;; The usual Emacs commands can be used to move by defuns
388 ;; (top-level major definitions). In markdown-mode, a defun is a
389 ;; section. As usual, `C-M-a` will move the point to the
390 ;; beginning of the current or preceding defun, `C-M-e` will move
391 ;; to the end of the current or following defun, and `C-M-h` will
392 ;; put the region around the entire defun.
393 ;;
394 ;; As noted, many of the commands above behave differently depending
395 ;; on whether Transient Mark mode is enabled or not. When it makes
396 ;; sense, if Transient Mark mode is on and the region is active, the
397 ;; command applies to the text in the region (e.g., `C-c C-s s` makes the
398 ;; region bold). For users who prefer to work outside of Transient
399 ;; Mark mode, since Emacs 22 it can be enabled temporarily by pressing
400 ;; `C-SPC C-SPC`. When this is not the case, many commands then
401 ;; proceed to look work with the word or line at the point.
402 ;;
403 ;; When applicable, commands that specifically act on the region even
404 ;; outside of Transient Mark mode have the same keybinding as their
405 ;; standard counterpart, but the letter is uppercase. For example,
406 ;; `markdown-insert-blockquote' is bound to `C-c C-s b` and only acts on
407 ;; the region in Transient Mark mode while `markdown-blockquote-region'
408 ;; is bound to `C-c C-s B` and always applies to the region (when nonempty).
409 ;;
410 ;; Note that these region-specific functions are useful in many
411 ;; cases where it may not be obvious. For example, yanking text from
412 ;; the kill ring sets the mark at the beginning of the yanked text
413 ;; and moves the point to the end. Therefore, the (inactive) region
414 ;; contains the yanked text. So, `C-y` followed by `C-c C-s C-b` will
415 ;; yank text and turn it into a blockquote.
416 ;;
417 ;; markdown-mode attempts to be flexible in how it handles
418 ;; indentation. When you press `TAB` repeatedly, the point will cycle
419 ;; through several possible indentation levels corresponding to things
420 ;; you might have in mind when you press `RET` at the end of a line or
421 ;; `TAB`. For example, you may want to start a new list item,
422 ;; continue a list item with hanging indentation, indent for a nested
423 ;; pre block, and so on. Exdention is handled similarly when backspace
424 ;; is pressed at the beginning of the non-whitespace portion of a line.
425 ;;
426 ;; markdown-mode supports outline-minor-mode as well as org-mode-style
427 ;; visibility cycling for atx- or hash-style headings. There are two
428 ;; types of visibility cycling: Pressing `S-TAB` cycles globally between
429 ;; the table of contents view (headings only), outline view (top-level
430 ;; headings only), and the full document view. Pressing `TAB` while the
431 ;; point is at a heading will cycle through levels of visibility for the
432 ;; subtree: completely folded, visible children, and fully visible.
433 ;; Note that mixing hash and underline style headings will give undesired
434 ;; results.
435
436 ;;; Customization:
437
438 ;; Although no configuration is *necessary* there are a few things
439 ;; that can be customized. The `M-x customize-mode` command
440 ;; provides an interface to all of the possible customizations:
441 ;;
442 ;; * `markdown-command' - the command used to run Markdown (default:
443 ;; `markdown`). This variable may be customized to pass
444 ;; command-line options to your Markdown processor of choice.
445 ;;
446 ;; * `markdown-command-needs-filename' - set to `t' if
447 ;; `markdown-command' does not accept standard input (default:
448 ;; `nil'). When `nil', `markdown-mode' will pass the Markdown
449 ;; content to `markdown-command' using standard input (`stdin`).
450 ;; When set to `t', `markdown-mode' will pass the name of the file
451 ;; as the final command-line argument to `markdown-command'. Note
452 ;; that in the latter case, you will only be able to run
453 ;; `markdown-command' from buffers which are visiting a file.
454 ;;
455 ;; * `markdown-open-command' - the command used for calling a standalone
456 ;; Markdown previewer which is capable of opening Markdown source files
457 ;; directly (default: `nil'). This command will be called
458 ;; with a single argument, the filename of the current buffer.
459 ;; A representative program is the Mac app [Marked][], a
460 ;; live-updating MultiMarkdown previewer which has a command line
461 ;; utility at `/usr/local/bin/mark`.
462 ;;
463 ;; * `markdown-hr-strings' - list of strings to use when inserting
464 ;; horizontal rules. Different strings will not be distinguished
465 ;; when converted to HTML--they will all be converted to
466 ;; `<hr/>`--but they may add visual distinction and style to plain
467 ;; text documents. To maintain some notion of promotion and
468 ;; demotion, keep these sorted from largest to smallest.
469 ;;
470 ;; * `markdown-bold-underscore' - set to a non-nil value to use two
471 ;; underscores for bold instead of two asterisks (default: `nil').
472 ;;
473 ;; * `markdown-italic-underscore' - set to a non-nil value to use
474 ;; underscores for italic instead of asterisks (default: `nil').
475 ;;
476 ;; * `markdown-indent-function' - the function to use for automatic
477 ;; indentation (default: `markdown-indent-line').
478 ;;
479 ;; * `markdown-indent-on-enter' - set to a non-nil value to
480 ;; automatically indent new lines when the enter key is pressed
481 ;; (default: `t')
482 ;;
483 ;; * `markdown-wiki-link-alias-first' - set to a non-nil value to
484 ;; treat aliased wiki links like `[[link text|PageName]]`
485 ;; (default: `t'). When set to nil, they will be treated as
486 ;; `[[PageName|link text]]'.
487 ;;
488 ;; * `markdown-uri-types' - a list of protocol schemes (e.g., "http")
489 ;; for URIs that `markdown-mode' should highlight.
490 ;;
491 ;; * `markdown-enable-math' - syntax highlighting for LaTeX
492 ;; fragments (default: `nil'). Set this to `t' to turn on math
493 ;; support by default. Math support can be toggled later using
494 ;; the function `markdown-enable-math'."
495 ;;
496 ;; * `markdown-css-path' - CSS file to link to in XHTML output
497 ;; (default: `""`).
498 ;;
499 ;; * `markdown-content-type' - when set to a nonempty string, an
500 ;; `http-equiv` attribute will be included in the XHTML `<head>`
501 ;; block (default: `""`). If needed, the suggested values are
502 ;; `application/xhtml+xml` or `text/html`. See also:
503 ;; `markdown-coding-system'.
504 ;;
505 ;; * `markdown-coding-system' - used for specifying the character
506 ;; set identifier in the `http-equiv` attribute when included
507 ;; (default: `nil'). See `markdown-content-type', which must
508 ;; be set before this variable has any effect. When set to `nil',
509 ;; `buffer-file-coding-system' will be used to automatically
510 ;; determine the coding system string (falling back to
511 ;; `iso-8859-1' when unavailable). Common settings are `utf-8'
512 ;; and `iso-latin-1'.
513 ;;
514 ;; * `markdown-xhtml-header-content' - additional content to include
515 ;; in the XHTML `<head>` block (default: `""`).
516 ;;
517 ;; * `markdown-xhtml-standalone-regexp' - a regular expression which
518 ;; `markdown-mode' uses to determine whether the output of
519 ;; `markdown-command' is a standalone XHTML document or an XHTML
520 ;; fragment (default: `"^\\(<\\?xml\\|<!DOCTYPE\\|<html\\)"`). If
521 ;; this regular expression not matched in the first five lines of
522 ;; output, `markdown-mode' assumes the output is a fragment and
523 ;; adds a header and footer.
524 ;;
525 ;; * `markdown-link-space-sub-char' - a character to replace spaces
526 ;; when mapping wiki links to filenames (default: `"_"`).
527 ;; For example, use an underscore for compatibility with the
528 ;; Python Markdown WikiLinks extension. In `gfm-mode', this is
529 ;; set to `"-"` to conform with GitHub wiki links.
530 ;;
531 ;; * `markdown-reference-location' - where to insert reference
532 ;; definitions (default: `header`). The possible locations are
533 ;; the end of the document (`end`), after the current block
534 ;; (`immediately`), before the next header (`header`).
535 ;;
536 ;; * `markdown-footnote-location' - where to insert footnote text
537 ;; (default: `end`). The set of location options is the same as
538 ;; for `markdown-reference-location'.
539 ;;
540 ;; * `comment-auto-fill-only-comments' - variable is made
541 ;; buffer-local and set to `nil' by default. In programming
542 ;; language modes, when this variable is non-nil, only comments
543 ;; will be filled by auto-fill-mode. However, comments in
544 ;; Markdown documents are rare and the most users probably intend
545 ;; for the actual content of the document to be filled. Making
546 ;; this variable buffer-local allows `markdown-mode' to override
547 ;; the default behavior induced when the global variable is non-nil.
548 ;;
549 ;; Additionally, the faces used for syntax highlighting can be modified to
550 ;; your liking by issuing `M-x customize-group RET markdown-faces`
551 ;; or by using the "Markdown Faces" link at the bottom of the mode
552 ;; customization screen.
553 ;;
554 ;; [Marked]: https://itunes.apple.com/us/app/marked/id448925439?ls=1&mt=12&partnerId=30&siteID=GpHp3Acs1Yo
555
556 ;;; Extensions:
557
558 ;; Besides supporting the basic Markdown syntax, markdown-mode also
559 ;; includes syntax highlighting for `[[Wiki Links]]` by default. Wiki
560 ;; links may be followed by pressing `C-c C-o` when the point
561 ;; is at a wiki link. Use `M-p` and `M-n` to quickly jump to the
562 ;; previous and next links (including links of other types).
563 ;; Aliased or piped wiki links of the form `[[link text|PageName]]`
564 ;; are also supported. Since some wikis reverse these components, set
565 ;; `markdown-wiki-link-alias-first' to nil to treat them as
566 ;; `[[PageName|link text]]`.
567 ;;
568 ;; [SmartyPants][] support is possible by customizing `markdown-command'.
569 ;; If you install `SmartyPants.pl` at, say, `/usr/local/bin/smartypants`,
570 ;; then you can set `markdown-command' to `"markdown | smartypants"`.
571 ;; You can do this either by using `M-x customize-group markdown`
572 ;; or by placing the following in your `.emacs` file:
573 ;;
574 ;; (defun markdown-custom ()
575 ;; "markdown-mode-hook"
576 ;; (setq markdown-command "markdown | smartypants"))
577 ;; (add-hook 'markdown-mode-hook '(lambda() (markdown-custom)))
578 ;;
579 ;; [SmartyPants]: http://daringfireball.net/projects/smartypants/
580 ;;
581 ;; Syntax highlighting for mathematical expressions written
582 ;; in LaTeX (only expressions denoted by `$..$`, `$$..$$`, or `\[..\]`)
583 ;; can be enabled by setting `markdown-enable-math' to a non-nil value,
584 ;; either via customize or by placing `(setq markdown-enable-math t)`
585 ;; in `.emacs`, and then restarting Emacs or calling
586 ;; `markdown-reload-extensions'.
587
588 ;;; GitHub Flavored Markdown:
589
590 ;; A [GitHub Flavored Markdown][GFM] (GFM) mode, `gfm-mode', is also
591 ;; available. The GitHub implementation of differs slightly from
592 ;; standard Markdown. The most important differences are that
593 ;; newlines are significant, triggering hard line breaks, and that
594 ;; underscores inside of words (e.g., variable names) need not be
595 ;; escaped. As such, `gfm-mode' turns off `auto-fill-mode' and turns
596 ;; on `visual-line-mode' (or `longlines-mode' if `visual-line-mode' is
597 ;; not available). Underscores inside of words (such as
598 ;; test_variable) will not trigger emphasis.
599 ;;
600 ;; Wiki links in this mode will be treated as on GitHub, with hyphens
601 ;; replacing spaces in filenames and where the first letter of the
602 ;; filename capitalized. For example, `[[wiki link]]' will map to a
603 ;; file named `Wiki-link` with the same extension as the current file.
604 ;;
605 ;; GFM code blocks, with optional programming language keywords, will
606 ;; be highlighted. They can be inserted with `C-c C-s P`. If there
607 ;; is an active region, the text in the region will be placed inside
608 ;; the code block. You will be prompted for the name of the language,
609 ;; but may press enter to continue without naming a language.
610 ;;
611 ;; For a more complete GitHub Flavored Markdown experience, consider
612 ;; adding README.md to your `auto-mode-alist':
613 ;;
614 ;; (add-to-list 'auto-mode-alist '("README\\.md\\'" . gfm-mode))
615 ;;
616 ;; For GFM preview can be powered by setting `markdown-command' to
617 ;; use [Docter][]. This may also be configured to work with [Marked][]
618 ;; for `markdown-open-command'.
619 ;;
620 ;; [GFM]: http://github.github.com/github-flavored-markdown/
621 ;; [Docter]: https://github.com/alampros/Docter
622
623 ;;; Acknowledgments:
624
625 ;; markdown-mode has benefited greatly from the efforts of the
626 ;; following people:
627 ;;
628 ;; * Cyril Brulebois <cyril.brulebois@enst-bretagne.fr> for Debian packaging.
629 ;; * Conal Elliott <conal@conal.net> for a font-lock regexp patch.
630 ;; * Edward O'Connor <hober0@gmail.com> for a font-lock regexp fix and
631 ;; GitHub Flavored Markdown mode (`gfm-mode').
632 ;; * Greg Bognar <greg_bognar@hms.harvard.edu> for menus and running
633 ;; `markdown' with an active region.
634 ;; * Daniel Burrows <dburrows@debian.org> for filing Debian bug #456592.
635 ;; * Peter S. Galbraith <psg@debian.org> for maintaining `emacs-goodies-el`.
636 ;; * Dmitry Dzhus <mail@sphinx.net.ru> for undefined reference checking.
637 ;; * Carsten Dominik <carsten@orgmode.org> for `org-mode', from which the
638 ;; visibility cycling functionality was derived, and for a bug fix
639 ;; related to `orgtbl-mode'.
640 ;; * Bryan Kyle <bryan.kyle@gmail.com> for indentation code.
641 ;; * Ben Voui <intrigeri@boum.org> for font-lock face customizations.
642 ;; * Ankit Solanki <ankit.solanki@gmail.com> for `longlines.el`
643 ;; compatibility and custom CSS.
644 ;; * Hilko Bengen <bengen@debian.org> for proper XHTML output.
645 ;; * Jose A. Ortega Ruiz <jao@gnu.org> for Emacs 23 fixes.
646 ;; * Nelson Minar <nelson@santafe.edu> for `html-helper-mode', from which
647 ;; comment matching functions were derived.
648 ;; * Alec Resnick <alec@sproutward.org> for bug reports.
649 ;; * Joost Kremers <joostkremers@fastmail.fm> for footnote-handling
650 ;; functions, bug reports regarding indentation, and
651 ;; fixes for byte-compilation warnings.
652 ;; * Peter Williams <pezra@barelyenough.org> for `fill-paragraph'
653 ;; enhancements.
654 ;; * George Ogata <george.ogata@gmail.com> for fixing several
655 ;; byte-compilation warnings.
656 ;; * Eric Merritt <ericbmerritt@gmail.com> for wiki link features.
657 ;; * Philippe Ivaldi <pivaldi@sfr.fr> for XHTML preview
658 ;; customizations and XHTML export.
659 ;; * Jeremiah Dodds <jeremiah.dodds@gmail.com> for supporting
660 ;; Markdown processors which do not accept input from stdin.
661 ;; * Werner Dittmann <werner.dittmann@t-online.de> for bug reports
662 ;; regarding the `cl` dependency and `auto-fill-mode' and indentation.
663 ;; * Scott Pfister <scott.pfister@gmail.com> for generalizing the space
664 ;; substitution character for mapping wiki links to filenames.
665 ;; * Marcin Kasperski <marcin.kasperski@mekk.waw.pl> for a patch to
666 ;; escape shell commands.
667 ;; * Christopher J. Madsen <cjm@cjmweb.net> for patches to fix a match
668 ;; data bug and to prefer `visual-line-mode' in `gfm-mode'.
669 ;; * Shigeru Fukaya <shigeru.fukaya@gmail.com> for better adherence to
670 ;; Emacs Lisp coding conventions.
671 ;; * Donald Ephraim Curtis <dcurtis@milkbox.net> for fixing the `fill-paragraph'
672 ;; regexp, refactoring the compilation and preview functions,
673 ;; heading font-lock generalizations, list renumbering,
674 ;; and kill ring save.
675 ;; * Kevin Porter <kportertx@gmail.com> for wiki link handling in `gfm-mode'.
676 ;; * Max Penet <max.penet@gmail.com> and Peter Eisentraut <peter_e@gmx.net>
677 ;; for an autoload token for `gfm-mode'.
678 ;; * Ian Yang <me@iany.me> for improving the reference definition regex.
679 ;; * Akinori Musha <knu@idaemons.org> for an imenu index function.
680 ;; * Michael Sperber <sperber@deinprogramm.de> for XEmacs fixes.
681 ;; * Francois Gannaz <francois.gannaz@free.fr> for suggesting charset
682 ;; declaration in XHTML output.
683 ;; * Zhenlei Jia <zhenlei.jia@gmail.com> for smart exdention function.
684 ;; * Matus Goljer <dota.keys@gmail.com> for improved wiki link following
685 ;; and GFM code block insertion.
686 ;; * Peter Jones <pjones@pmade.com> for link following functions.
687 ;; * Bryan Fink <bryan.fink@gmail.com> for a bug report regarding
688 ;; externally modified files.
689 ;; * Vegard Vesterheim <vegard.vesterheim@uninett.no> for a bug fix
690 ;; related to `orgtbl-mode'.
691 ;; * Makoto Motohashi <mkt.motohashi@gmail.com> for before- and after-
692 ;; export hooks, unit test improvements, and updates to support
693 ;; wide characters.
694 ;; * Michael Dwyer <mdwyer@ehtech.in> for `gfm-mode' underscore regexp.
695 ;; * Chris Lott <chris@chrislott.org> for suggesting reference label
696 ;; completion.
697 ;; * Gunnar Franke <Gunnar.Franke@gmx.de> for a completion bug report.
698 ;; * David Glasser <glasser@meteor.com> for a `paragraph-separate' fix.
699 ;; * Daniel Brotsky <dev@brotsky.com> for better auto-fill defaults.
700
701 ;;; Bugs:
702
703 ;; Although markdown-mode is developed and tested primarily using
704 ;; GNU Emacs 24, compatibility with earlier Emacsen is also a
705 ;; priority.
706 ;;
707 ;; If you find any bugs in markdown-mode, please construct a test case
708 ;; or a patch and email me at <jrblevin@sdf.org>.
709
710 ;;; History:
711
712 ;; markdown-mode was written and is maintained by Jason Blevins. The
713 ;; first version was released on May 24, 2007.
714 ;;
715 ;; * 2007-05-24: Version 1.1
716 ;; * 2007-05-25: Version 1.2
717 ;; * 2007-06-05: [Version 1.3][]
718 ;; * 2007-06-29: Version 1.4
719 ;; * 2007-10-11: [Version 1.5][]
720 ;; * 2008-06-04: [Version 1.6][]
721 ;; * 2009-10-01: [Version 1.7][]
722 ;; * 2011-08-12: [Version 1.8][]
723 ;; * 2011-08-15: [Version 1.8.1][]
724 ;; * 2013-01-25: [Version 1.9][]
725 ;; * 2013-03-24: [Version 2.0][]
726 ;;
727 ;; [Version 1.3]: http://jblevins.org/projects/markdown-mode/rev-1-3
728 ;; [Version 1.5]: http://jblevins.org/projects/markdown-mode/rev-1-5
729 ;; [Version 1.6]: http://jblevins.org/projects/markdown-mode/rev-1-6
730 ;; [Version 1.7]: http://jblevins.org/projects/markdown-mode/rev-1-7
731 ;; [Version 1.8]: http://jblevins.org/projects/markdown-mode/rev-1-8
732 ;; [Version 1.8.1]: http://jblevins.org/projects/markdown-mode/rev-1-8-1
733 ;; [Version 1.9]: http://jblevins.org/projects/markdown-mode/rev-1-9
734 ;; [Version 2.0]: http://jblevins.org/projects/markdown-mode/rev-2-0
735
736 \f
737 ;;; Code:
738
739 (require 'easymenu)
740 (require 'outline)
741 (require 'thingatpt)
742 (eval-when-compile (require 'cl))
743
744 \f
745 ;;; Constants =================================================================
746
747 (defconst markdown-mode-version "2.0"
748 "Markdown mode version number.")
749
750 (defconst markdown-output-buffer-name "*markdown-output*"
751 "Name of temporary buffer for markdown command output.")
752
753 \f
754 ;;; Global Variables ==========================================================
755
756 (defvar markdown-reference-label-history nil
757 "History of used reference labels.")
758
759 \f
760 ;;; Customizable Variables ====================================================
761
762 (defvar markdown-mode-hook nil
763 "Hook run when entering Markdown mode.")
764
765 (defvar markdown-before-export-hook nil
766 "Hook run before running Markdown to export XHTML output.
767 The hook may modify the buffer, which will be restored to it's
768 original state after exporting is complete.")
769
770 (defvar markdown-after-export-hook nil
771 "Hook run after XHTML output has been saved.
772 Any changes to the output buffer made by this hook will be saved.")
773
774 (defgroup markdown nil
775 "Major mode for editing text files in Markdown format."
776 :prefix "markdown-"
777 :group 'wp
778 :link '(url-link "http://jblevins.org/projects/markdown-mode/"))
779
780 (defcustom markdown-command "markdown"
781 "Command to run markdown."
782 :group 'markdown
783 :type 'string)
784
785 (defcustom markdown-command-needs-filename nil
786 "Set to non-nil if `markdown-command' does not accept input from stdin.
787 Instead, it will be passed a filename as the final command line
788 option. As a result, you will only be able to run Markdown from
789 buffers which are visiting a file."
790 :group 'markdown
791 :type 'boolean)
792
793 (defcustom markdown-open-command nil
794 "Command used for opening Markdown files directly.
795 For example, a standalone Markdown previewer. This command will
796 be called with a single argument: the filename of the current
797 buffer."
798 :group 'markdown
799 :type 'string)
800
801 (defcustom markdown-hr-strings
802 '("-------------------------------------------------------------------------------"
803 "* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *"
804 "---------------------------------------"
805 "* * * * * * * * * * * * * * * * * * * *"
806 "---------"
807 "* * * * *")
808 "Strings to use when inserting horizontal rules.
809 The first string in the list will be the default when inserting a
810 horizontal rule. Strings should be listed in decreasing order of
811 prominence (as in headings from level one to six) for use with
812 promotion and demotion functions."
813 :group 'markdown
814 :type 'list)
815
816 (defcustom markdown-bold-underscore nil
817 "Use two underscores for bold instead of two asterisks."
818 :group 'markdown
819 :type 'boolean)
820
821 (defcustom markdown-italic-underscore nil
822 "Use underscores for italic instead of asterisks."
823 :group 'markdown
824 :type 'boolean)
825
826 (defcustom markdown-indent-function 'markdown-indent-line
827 "Function to use to indent."
828 :group 'markdown
829 :type 'function)
830
831 (defcustom markdown-indent-on-enter t
832 "Automatically indent new lines when enter key is pressed.
833 When this variable is set to t, pressing RET will call
834 `newline-and-indent'. When set to nil, define RET to call
835 `newline' as usual. In the latter case, you can still use
836 auto-indentation by pressing \\[newline-and-indent]."
837 :group 'markdown
838 :type 'boolean)
839
840 (defcustom markdown-wiki-link-alias-first t
841 "When non-nil, treat aliased wiki links like [[alias text|PageName]].
842 Otherwise, they will be treated as [[PageName|alias text]]."
843 :group 'markdown
844 :type 'boolean)
845
846 (defcustom markdown-uri-types
847 '("acap" "cid" "data" "dav" "fax" "file" "ftp" "gopher" "http" "https"
848 "imap" "ldap" "mailto" "mid" "modem" "news" "nfs" "nntp" "pop" "prospero"
849 "rtsp" "service" "sip" "tel" "telnet" "tip" "urn" "vemmi" "wais")
850 "Link types for syntax highlighting of URIs."
851 :group 'markdown
852 :type 'list)
853
854 (defcustom markdown-enable-math nil
855 "Syntax highlighting for inline LaTeX and itex expressions.
856 Set this to a non-nil value to turn on math support by default.
857 Math support can be toggled later using `markdown-enable-math'
858 or \\[markdown-enable-math]."
859 :group 'markdown
860 :type 'boolean
861 :safe 'booleanp)
862
863 (defcustom markdown-css-path ""
864 "URL of CSS file to link to in the output XHTML."
865 :group 'markdown
866 :type 'string)
867
868 (defcustom markdown-content-type ""
869 "Content type string for the http-equiv header in XHTML output.
870 When set to a non-empty string, insert the http-equiv attribute.
871 Otherwise, this attribute is omitted."
872 :group 'markdown
873 :type 'string)
874
875 (defcustom markdown-coding-system nil
876 "Character set string for the http-equiv header in XHTML output.
877 Defaults to `buffer-file-coding-system' (and falling back to
878 `iso-8859-1' when not available). Common settings are `utf-8'
879 and `iso-latin-1'. Use `list-coding-systems' for more choices."
880 :group 'markdown
881 :type 'coding-system)
882
883 (defcustom markdown-xhtml-header-content ""
884 "Additional content to include in the XHTML <head> block."
885 :group 'markdown
886 :type 'string)
887
888 (defcustom markdown-xhtml-standalone-regexp
889 "^\\(<\\?xml\\|<!DOCTYPE\\|<html\\)"
890 "Regexp indicating whether `markdown-command' output is standalone XHTML."
891 :group 'markdown
892 :type 'regexp)
893
894 (defcustom markdown-link-space-sub-char "_"
895 "Character to use instead of spaces when mapping wiki links to filenames."
896 :group 'markdown
897 :type 'string)
898
899 (defcustom markdown-reference-location 'header
900 "Position where new reference definitions are inserted in the document."
901 :group 'markdown
902 :type '(choice (const :tag "At the end of the document" end)
903 (const :tag "Immediately after the current block" immediately)
904 (const :tag "Before next header" header)))
905
906 (defcustom markdown-footnote-location 'end
907 "Position where new footnotes are inserted in the document."
908 :group 'markdown
909 :type '(choice (const :tag "At the end of the document" end)
910 (const :tag "Immediately after the current block" immediately)
911 (const :tag "Before next header" header)))
912
913 \f
914 ;;; Font Lock =================================================================
915
916 (require 'font-lock)
917
918 (defvar markdown-italic-face 'markdown-italic-face
919 "Face name to use for italic text.")
920
921 (defvar markdown-bold-face 'markdown-bold-face
922 "Face name to use for bold text.")
923
924 (defvar markdown-header-delimiter-face 'markdown-header-delimiter-face
925 "Face name to use as a base for header delimiters.")
926
927 (defvar markdown-header-rule-face 'markdown-header-rule-face
928 "Face name to use as a base for header rules.")
929
930 (defvar markdown-header-face 'markdown-header-face
931 "Face name to use as a base for headers.")
932
933 (defvar markdown-header-face-1 'markdown-header-face-1
934 "Face name to use for level-1 headers.")
935
936 (defvar markdown-header-face-2 'markdown-header-face-2
937 "Face name to use for level-2 headers.")
938
939 (defvar markdown-header-face-3 'markdown-header-face-3
940 "Face name to use for level-3 headers.")
941
942 (defvar markdown-header-face-4 'markdown-header-face-4
943 "Face name to use for level-4 headers.")
944
945 (defvar markdown-header-face-5 'markdown-header-face-5
946 "Face name to use for level-5 headers.")
947
948 (defvar markdown-header-face-6 'markdown-header-face-6
949 "Face name to use for level-6 headers.")
950
951 (defvar markdown-inline-code-face 'markdown-inline-code-face
952 "Face name to use for inline code.")
953
954 (defvar markdown-list-face 'markdown-list-face
955 "Face name to use for list markers.")
956
957 (defvar markdown-blockquote-face 'markdown-blockquote-face
958 "Face name to use for blockquote.")
959
960 (defvar markdown-pre-face 'markdown-pre-face
961 "Face name to use for preformatted text.")
962
963 (defvar markdown-language-keyword-face 'markdown-language-keyword-face
964 "Face name to use for programming language identifiers.")
965
966 (defvar markdown-link-face 'markdown-link-face
967 "Face name to use for links.")
968
969 (defvar markdown-missing-link-face 'markdown-missing-link-face
970 "Face name to use for links where the linked file does not exist.")
971
972 (defvar markdown-reference-face 'markdown-reference-face
973 "Face name to use for reference.")
974
975 (defvar markdown-footnote-face 'markdown-footnote-face
976 "Face name to use for footnote identifiers.")
977
978 (defvar markdown-url-face 'markdown-url-face
979 "Face name to use for URLs.")
980
981 (defvar markdown-link-title-face 'markdown-link-title-face
982 "Face name to use for reference link titles.")
983
984 (defvar markdown-line-break-face 'markdown-line-break-face
985 "Face name to use for hard line breaks.")
986
987 (defvar markdown-comment-face 'markdown-comment-face
988 "Face name to use for HTML comments.")
989
990 (defvar markdown-math-face 'markdown-math-face
991 "Face name to use for LaTeX expressions.")
992
993 (defvar markdown-metadata-key-face 'markdown-metadata-key-face
994 "Face name to use for metadata keys.")
995
996 (defvar markdown-metadata-value-face 'markdown-metadata-value-face
997 "Face name to use for metadata values.")
998
999 (defgroup markdown-faces nil
1000 "Faces used in Markdown Mode"
1001 :group 'markdown
1002 :group 'faces)
1003
1004 (defface markdown-italic-face
1005 '((t (:inherit font-lock-variable-name-face :slant italic)))
1006 "Face for italic text."
1007 :group 'markdown-faces)
1008
1009 (defface dislines-face
1010 '((t (:inherit font-lock-type-face :slant italic)))
1011 "Face for dislines markers."
1012 :group 'markdown-faces)
1013
1014 (defface markdown-bold-face
1015 '((t (:inherit font-lock-variable-name-face :weight bold)))
1016 "Face for bold text."
1017 :group 'markdown-faces)
1018
1019 (defface markdown-header-rule-face
1020 '((t (:inherit font-lock-function-name-face :weight bold)))
1021 "Base face for headers rules."
1022 :group 'markdown-faces)
1023
1024 (defface markdown-header-delimiter-face
1025 '((t (:inherit font-lock-function-name-face :weight bold)))
1026 "Base face for headers hash delimiter."
1027 :group 'markdown-faces)
1028
1029 (defface markdown-header-face
1030 '((t (:inherit font-lock-function-name-face :weight bold)))
1031 "Base face for headers."
1032 :group 'markdown-faces)
1033
1034 (defface markdown-header-face-1
1035 '((t (:inherit markdown-header-face)))
1036 "Face for level-1 headers."
1037 :group 'markdown-faces)
1038
1039 (defface markdown-header-face-2
1040 '((t (:inherit markdown-header-face)))
1041 "Face for level-2 headers."
1042 :group 'markdown-faces)
1043
1044 (defface markdown-header-face-3
1045 '((t (:inherit markdown-header-face)))
1046 "Face for level-3 headers."
1047 :group 'markdown-faces)
1048
1049 (defface markdown-header-face-4
1050 '((t (:inherit markdown-header-face)))
1051 "Face for level-4 headers."
1052 :group 'markdown-faces)
1053
1054 (defface markdown-header-face-5
1055 '((t (:inherit markdown-header-face)))
1056 "Face for level-5 headers."
1057 :group 'markdown-faces)
1058
1059 (defface markdown-header-face-6
1060 '((t (:inherit markdown-header-face)))
1061 "Face for level-6 headers."
1062 :group 'markdown-faces)
1063
1064 (defface markdown-inline-code-face
1065 '((t (:inherit font-lock-constant-face)))
1066 "Face for inline code."
1067 :group 'markdown-faces)
1068
1069 (defface markdown-list-face
1070 '((t (:inherit font-lock-builtin-face)))
1071 "Face for list item markers."
1072 :group 'markdown-faces)
1073
1074 (defface markdown-blockquote-face
1075 '((t (:inherit font-lock-doc-face)))
1076 "Face for blockquote sections."
1077 :group 'markdown-faces)
1078
1079 (defface markdown-pre-face
1080 '((t (:inherit font-lock-constant-face)))
1081 "Face for preformatted text."
1082 :group 'markdown-faces)
1083
1084 (defface markdown-language-keyword-face
1085 '((t (:inherit font-lock-type-face)))
1086 "Face for programming language identifiers."
1087 :group 'markdown-faces)
1088
1089 (defface markdown-link-face
1090 '((t (:inherit font-lock-keyword-face)))
1091 "Face for links."
1092 :group 'markdown-faces)
1093
1094 (defface markdown-missing-link-face
1095 '((t (:inherit font-lock-warning-face)))
1096 "Face for missing links."
1097 :group 'markdown-faces)
1098
1099 (defface markdown-reference-face
1100 '((t (:inherit font-lock-type-face)))
1101 "Face for link references."
1102 :group 'markdown-faces)
1103
1104 (defface markdown-footnote-face
1105 '((t (:inherit font-lock-keyword-face)))
1106 "Face for footnote markers."
1107 :group 'markdown-faces)
1108
1109 (defface markdown-url-face
1110 '((t (:inherit font-lock-string-face)))
1111 "Face for URLs."
1112 :group 'markdown-faces)
1113
1114 (defface markdown-link-title-face
1115 '((t (:inherit font-lock-comment-face)))
1116 "Face for reference link titles."
1117 :group 'markdown-faces)
1118
1119 (defface markdown-line-break-face
1120 '((t (:inherit font-lock-constant-face :underline t)))
1121 "Face for hard line breaks."
1122 :group 'markdown-faces)
1123
1124 (defface markdown-comment-face
1125 '((t (:inherit font-lock-comment-face)))
1126 "Face for HTML comments."
1127 :group 'markdown-faces)
1128
1129 (defface markdown-math-face
1130 '((t (:inherit font-lock-string-face)))
1131 "Face for LaTeX expressions."
1132 :group 'markdown-faces)
1133
1134 (defface markdown-metadata-key-face
1135 '((t (:inherit font-lock-variable-name-face)))
1136 "Face for metadata keys."
1137 :group 'markdown-faces)
1138
1139 (defface markdown-metadata-value-face
1140 '((t (:inherit font-lock-string-face)))
1141 "Face for metadata values."
1142 :group 'markdown-faces)
1143
1144 (defconst markdown-regex-link-inline
1145 "\\(!\\)?\\(\\[\\([^]^][^]]*\\|\\)\\]\\)\\((\\([^)]*?\\)\\(?:\\s-+\\(\"[^\"]*\"\\)\\)?)\\)"
1146 "Regular expression for a [text](file) or an image link ![text](file).
1147 Group 1 matches the leading exclamation point, if any.
1148 Group 2 matchs the entire square bracket term, including the text.
1149 Group 3 matches the text inside the square brackets.
1150 Group 4 matches the entire parenthesis term, including the URL and title.
1151 Group 5 matches the URL.
1152 Group 6 matches (optional) title.")
1153
1154 (defconst markdown-regex-link-reference
1155 "\\(!\\)?\\(\\[\\([^]^][^]]*\\|\\)\\]\\)[ ]?\\(\\[\\([^]]*?\\)\\]\\)"
1156 "Regular expression for a reference link [text][id].
1157 Group 1 matches the leading exclamation point, if any.
1158 Group 2 matchs the entire first square bracket term, including the text.
1159 Group 3 matches the text inside the square brackets.
1160 Group 4 matches the entire second square bracket term.
1161 Group 5 matches the reference label.")
1162
1163 (defconst markdown-regex-reference-definition
1164 "^ \\{0,3\\}\\(\\[[^\n]+?\\]\\):\\s *\\(.*?\\)\\s *\\( \"[^\"]*\"$\\|$\\)"
1165 "Regular expression for a link definition [id]: ...")
1166
1167 (defconst markdown-regex-footnote
1168 "\\(\\[\\^.+?\\]\\)"
1169 "Regular expression for a footnote marker [^fn].")
1170
1171 (defconst markdown-regex-header
1172 "^\\(?:\\(.+\\)\n\\(=+\\)\\|\\(.+\\)\n\\(-+\\)\\|\\(#+\\)\\s-*\\(.*?\\)\\s-*?\\(#*\\)\\)$"
1173 "Regexp identifying Markdown headers.")
1174
1175 (defconst markdown-regex-header-1-atx
1176 "^\\(#\\)[ \t]*\\(.+?\\)[ \t]*\\(#*\\)$"
1177 "Regular expression for level 1 atx-style (hash mark) headers.")
1178
1179 (defconst markdown-regex-header-2-atx
1180 "^\\(##\\)[ \t]*\\(.+?\\)[ \t]*\\(#*\\)$"
1181 "Regular expression for level 2 atx-style (hash mark) headers.")
1182
1183 (defconst markdown-regex-header-3-atx
1184 "^\\(###\\)[ \t]*\\(.+?\\)[ \t]*\\(#*\\)$"
1185 "Regular expression for level 3 atx-style (hash mark) headers.")
1186
1187 (defconst markdown-regex-header-4-atx
1188 "^\\(####\\)[ \t]*\\(.+?\\)[ \t]*\\(#*\\)$"
1189 "Regular expression for level 4 atx-style (hash mark) headers.")
1190
1191 (defconst markdown-regex-header-5-atx
1192 "^\\(#####\\)[ \t]*\\(.+?\\)[ \t]*\\(#*\\)$"
1193 "Regular expression for level 5 atx-style (hash mark) headers.")
1194
1195 (defconst markdown-regex-header-6-atx
1196 "^\\(######\\)[ \t]*\\(.+?\\)[ \t]*\\(#*\\)$"
1197 "Regular expression for level 6 atx-style (hash mark) headers.")
1198
1199 (defconst markdown-regex-header-1-setext
1200 "^\\(.*\\)\n\\(=+\\)$"
1201 "Regular expression for level 1 setext-style (underline) headers.")
1202
1203 (defconst markdown-regex-header-2-setext
1204 "^\\(.*\\)\n\\(-+\\)$"
1205 "Regular expression for level 2 setext-style (underline) headers.")
1206
1207 (defconst markdown-regex-header-setext
1208 "^\\(.+\\)\n\\(\\(?:=\\|-\\)+\\)$"
1209 "Regular expression for generic setext-style (underline) headers.")
1210
1211 (defconst markdown-regex-header-atx
1212 "^\\(#+\\)[ \t]*\\(.*?\\)[ \t]*\\(#*\\)$"
1213 "Regular expression for generic atx-style (hash mark) headers.")
1214
1215 (defconst markdown-regex-hr
1216 "^\\(\\*[ ]?\\*[ ]?\\*[ ]?[\\* ]*\\|-[ ]?-[ ]?-[--- ]*\\)$"
1217 "Regular expression for matching Markdown horizontal rules.")
1218
1219 (defconst markdown-regex-code
1220 "\\(\\`\\|[^\\]\\)\\(\\(`+\\)\\(\\(.\\|\n[^\n]\\)*?[^`]\\)\\3\\)\\([^`]\\|\\'\\)"
1221 "Regular expression for matching inline code fragments.
1222
1223 The first group ensures that the leading backquote character
1224 is not escaped. The group \\(.\\|\n[^\n]\\) matches any
1225 character, including newlines, but not two newlines in a row.
1226 The final group requires that the character following the code
1227 fragment is not a backquote.")
1228
1229 (defconst markdown-regex-pre
1230 "^\\( \\|\t\\).*$"
1231 "Regular expression for matching preformatted text sections.")
1232
1233 (defconst markdown-regex-list
1234 "^\\([ \t]*\\)\\([0-9]+\\.\\|[\\*\\+-]\\)\\([ \t]+\\)"
1235 "Regular expression for matching list items.")
1236
1237 (defconst markdown-regex-bold
1238 "\\(^\\|[^\\]\\)\\(\\([*_]\\{2\\}\\)\\([^ \n\t\\]\\|[^ \n\t]\\(?:.\\|\n[^\n]\\)*?[^\\ ]\\)\\(\\3\\)\\)"
1239 "Regular expression for matching bold text.
1240 Group 1 matches the character before the opening asterisk or
1241 underscore, if any, ensuring that it is not a backslash escape.
1242 Group 2 matches the entire expression, including delimiters.
1243 Groups 3 and 5 matches the opening and closing delimiters.
1244 Group 4 matches the text inside the delimiters.")
1245
1246 (defconst markdown-regex-italic
1247 "\\(^\\|[^\\]\\)\\(\\([*_]\\)\\([^ \n\t\\]\\|[^ \n\t]\\(?:.\\|\n[^\n]\\)*?[^\\ ]\\)\\(\\3\\)\\)"
1248 "Regular expression for matching italic text.
1249 Group 1 matches the character before the opening asterisk or
1250 underscore, if any, ensuring that it is not a backslash escape.
1251 Group 2 matches the entire expression, including delimiters.
1252 Groups 3 and 5 matches the opening and closing delimiters.
1253 Group 4 matches the text inside the delimiters.")
1254
1255 (defconst markdown-regex-gfm-italic
1256 "\\(^\\|\\s-\\)\\(\\([*_]\\)\\([^ \\]\\3\\|[^ ]\\(.\\|\n[^\n]\\)*?[^\\ ]\\3\\)\\)"
1257 "Regular expression for matching italic text in GitHub Flavored Markdown.
1258 Underscores in words are not treated as special.")
1259
1260 (defconst markdown-regex-blockquote
1261 "^[ \t]*\\(>\\).*$"
1262 "Regular expression for matching blockquote lines.")
1263
1264 (defconst markdown-regex-line-break
1265 "[^ \n\t][ \t]*\\( \\)$"
1266 "Regular expression for matching line breaks.")
1267
1268 (defconst markdown-regex-wiki-link
1269 "\\(?:^\\|[^\\]\\)\\(\\[\\[\\([^]|]+\\)\\(|\\([^]]+\\)\\)?\\]\\]\\)"
1270 "Regular expression for matching wiki links.
1271 This matches typical bracketed [[WikiLinks]] as well as 'aliased'
1272 wiki links of the form [[PageName|link text]]. In this regular
1273 expression, group 1 matches the entire link, including square
1274 brackets, group 2 matches the first component of the wiki link
1275 and group 4 matches the second component, after the pipe, when
1276 present. The meanings of the first and second components depend
1277 on the value of `markdown-wiki-link-alias-first'.")
1278
1279 (defconst markdown-regex-uri
1280 (concat (regexp-opt markdown-uri-types) ":[^]\t\n\r<>,;() ]+")
1281 "Regular expression for matching inline URIs.")
1282
1283 (defconst markdown-regex-angle-uri
1284 (concat "\\(<\\)\\(" (regexp-opt markdown-uri-types) ":[^]\t\n\r<>,;()]+\\)\\(>\\)")
1285 "Regular expression for matching inline URIs in angle brackets.")
1286
1287 (defconst markdown-regex-email
1288 "<\\(\\(\\sw\\|\\s_\\|\\s.\\)+@\\(\\sw\\|\\s_\\|\\s.\\)+\\)>"
1289 "Regular expression for matching inline email addresses.")
1290
1291 (defconst markdown-regex-link-generic
1292 (concat "\\(?:" markdown-regex-wiki-link
1293 "\\|" markdown-regex-link-inline
1294 "\\|" markdown-regex-link-reference
1295 "\\|" markdown-regex-angle-uri "\\)")
1296 "Regular expression for matching any recognized link.")
1297
1298 (defconst markdown-regex-block-separator
1299 "\\(\\`\\|\\(\n[ \t]*\n\\)[^\n \t]\\)"
1300 "Regular expression for matching block boundaries.")
1301
1302 (defconst markdown-regex-math-inline
1303 "\\(^\\|[^\\]\\)\\(\\$\\($\\([^\\$]\\|\\\\.\\)*\\$\\|\\([^\\$]\\|\\\\.\\)*\\)\\$\\)"
1304 "Regular expression for itex $..$ or $$..$$ math mode expressions.")
1305
1306 (defconst markdown-regex-math-display
1307 "^\\\\\\[\\(.\\|\n\\)*?\\\\\\]$"
1308 "Regular expression for itex \[..\] display mode expressions.")
1309
1310 (defconst markdown-regex-multimarkdown-metadata
1311 "^\\([[:alpha:]][[:alpha:] _-]*?\\):[ \t]*\\(.*\\)$"
1312 "Regular expression for matching MultiMarkdown metadata.")
1313
1314 (defconst markdown-regex-pandoc-metadata
1315 "^\\(%\\)[ \t]*\\(.*\\)$"
1316 "Regular expression for matching Pandoc metadata.")
1317 (defconst dislines-markdown-translation-string
1318 "^\\(@+[@\"a-z{},]+\\)"
1319 "Regular expression that matches the dislines translation strings"
1320 )
1321
1322 (defvar markdown-mode-font-lock-keywords-basic
1323 (list
1324 (cons 'markdown-match-pre-blocks '((0 markdown-pre-face)))
1325 (cons 'markdown-match-fenced-code-blocks '((0 markdown-pre-face)))
1326 (cons markdown-regex-blockquote 'markdown-blockquote-face)
1327 (cons markdown-regex-header-1-setext '((1 markdown-header-face-1)
1328 (2 markdown-header-rule-face)))
1329 (cons markdown-regex-header-2-setext '((1 markdown-header-face-2)
1330 (2 markdown-header-rule-face)))
1331 (cons markdown-regex-header-6-atx '((1 markdown-header-delimiter-face)
1332 (2 markdown-header-face-6)
1333 (3 markdown-header-delimiter-face)))
1334 (cons markdown-regex-header-5-atx '((1 markdown-header-delimiter-face)
1335 (2 markdown-header-face-5)
1336 (3 markdown-header-delimiter-face)))
1337 (cons markdown-regex-header-4-atx '((1 markdown-header-delimiter-face)
1338 (2 markdown-header-face-4)
1339 (3 markdown-header-delimiter-face)))
1340 (cons markdown-regex-header-3-atx '((1 markdown-header-delimiter-face)
1341 (2 markdown-header-face-3)
1342 (3 markdown-header-delimiter-face)))
1343 (cons markdown-regex-header-2-atx '((1 markdown-header-delimiter-face)
1344 (2 markdown-header-face-2)
1345 (3 markdown-header-delimiter-face)))
1346 (cons markdown-regex-header-1-atx '((1 markdown-header-delimiter-face)
1347 (2 markdown-header-face-1)
1348 (3 markdown-header-delimiter-face)))
1349 (cons 'markdown-match-multimarkdown-metadata '((1 markdown-metadata-key-face)
1350 (2 markdown-metadata-value-face)))
1351 (cons 'markdown-match-pandoc-metadata '((1 markdown-comment-face)
1352 (2 markdown-metadata-value-face)))
1353 (cons markdown-regex-hr 'markdown-header-face)
1354 (cons 'markdown-match-comments '((0 markdown-comment-face)))
1355 (cons 'markdown-match-code '((0 markdown-inline-code-face)))
1356 (cons markdown-regex-angle-uri 'markdown-link-face)
1357 (cons markdown-regex-uri 'markdown-link-face)
1358 (cons markdown-regex-email 'markdown-link-face)
1359 (cons markdown-regex-list '(2 markdown-list-face))
1360 (cons markdown-regex-footnote 'markdown-footnote-face)
1361 (cons markdown-regex-link-inline '((1 markdown-link-face t t)
1362 (2 markdown-link-face t)
1363 (4 markdown-url-face t)
1364 (6 markdown-link-title-face t t)))
1365 (cons markdown-regex-link-reference '((1 markdown-link-face t t)
1366 (2 markdown-link-face t)
1367 (4 markdown-reference-face t)))
1368 (cons markdown-regex-reference-definition '((1 markdown-reference-face t)
1369 (2 markdown-url-face t)
1370 (3 markdown-link-title-face t)))
1371 (cons markdown-regex-bold '(2 markdown-bold-face))
1372 (cons markdown-regex-line-break '(1 markdown-line-break-face prepend))
1373 (cons dislines-markdown-translation-string '((0 markdown-comment-face)))
1374 )
1375 "Syntax highlighting for Markdown files.")
1376
1377 (defvar markdown-mode-font-lock-keywords-core
1378 (list
1379 (cons markdown-regex-italic '(2 markdown-italic-face))
1380 )
1381 "Additional syntax highlighting for Markdown files.
1382 Includes features which are overridden by some variants.")
1383
1384 (defconst markdown-mode-font-lock-keywords-math
1385 (list
1386 ;; Math mode $..$ or $$..$$
1387 (cons markdown-regex-math-inline '(2 markdown-math-face))
1388 ;; Display mode equations with brackets: \[ \]
1389 (cons markdown-regex-math-display 'markdown-math-face)
1390 ;; Equation reference (eq:foo)
1391 (cons "(eq:[[:alnum:]:_]+)" 'markdown-reference-face)
1392 ;; Equation reference \eqref{foo}
1393 (cons "\\\\eqref{[[:alnum:]:_]+}" 'markdown-reference-face))
1394 "Syntax highlighting for LaTeX and itex fragments.")
1395
1396 (defvar markdown-mode-font-lock-keywords nil
1397 "Default highlighting expressions for Markdown mode.
1398 This variable is defined as a buffer-local variable for dynamic
1399 extension support.")
1400
1401 ;; Footnotes
1402 (defvar markdown-footnote-counter 0
1403 "Counter for footnote numbers.")
1404 (make-variable-buffer-local 'markdown-footnote-counter)
1405
1406 (defconst markdown-footnote-chars
1407 "[[:alnum:]-]"
1408 "Regular expression maching any character that is allowed in a footnote identifier.")
1409
1410 \f
1411 ;;; Compatibility =============================================================
1412
1413 (defun markdown-replace-regexp-in-string (regexp rep string)
1414 "Replace ocurrences of REGEXP with REP in STRING.
1415 This is a compatibility wrapper to provide `replace-regexp-in-string'
1416 in XEmacs 21."
1417 (if (featurep 'xemacs)
1418 (replace-in-string string regexp rep)
1419 (replace-regexp-in-string regexp rep string)))
1420
1421 ;; `markdown-use-region-p' is a compatibility function which checks
1422 ;; for an active region, with fallbacks for older Emacsen and XEmacs.
1423 (eval-and-compile
1424 (cond
1425 ;; Emacs 23 and newer
1426 ((fboundp 'use-region-p)
1427 (defalias 'markdown-use-region-p 'use-region-p))
1428 ;; Older Emacsen
1429 ((and (boundp 'transient-mark-mode) (boundp 'mark-active))
1430 (defun markdown-use-region-p ()
1431 "Compatibility wrapper to provide `use-region-p'."
1432 (and transient-mark-mode mark-active)))
1433 ;; XEmacs
1434 ((fboundp 'region-active-p)
1435 (defalias 'markdown-use-region-p 'region-active-p))))
1436
1437 (defun markdown-use-buttons-p ()
1438 "Determine whether this Emacs supports buttons."
1439 (or (featurep 'button) (locate-library "button")))
1440
1441 \f
1442 ;;; Markdown Parsing Functions ================================================
1443
1444 (defun markdown-cur-line-blank-p ()
1445 "Return t if the current line is blank and nil otherwise."
1446 (save-excursion
1447 (beginning-of-line)
1448 (re-search-forward "^\\s *$" (line-end-position) t)))
1449
1450 (defun markdown-prev-line-blank-p ()
1451 "Return t if the previous line is blank and nil otherwise.
1452 If we are at the first line, then consider the previous line to be blank."
1453 (or (= (line-beginning-position) (point-min))
1454 (save-excursion
1455 (forward-line -1)
1456 (markdown-cur-line-blank-p))))
1457
1458 (defun markdown-next-line-blank-p ()
1459 "Return t if the next line is blank and nil otherwise.
1460 If we are at the last line, then consider the next line to be blank."
1461 (or (= (line-end-position) (point-max))
1462 (save-excursion
1463 (forward-line 1)
1464 (markdown-cur-line-blank-p))))
1465
1466 (defun markdown-prev-line-indent-p ()
1467 "Return t if the previous line is indented and nil otherwise."
1468 (save-excursion
1469 (forward-line -1)
1470 (goto-char (line-beginning-position))
1471 (if (re-search-forward "^\\s " (line-end-position) t) t)))
1472
1473 (defun markdown-cur-line-indent ()
1474 "Return the number of leading whitespace characters in the current line."
1475 (save-match-data
1476 (save-excursion
1477 (goto-char (line-beginning-position))
1478 (re-search-forward "^[ \t]+" (line-end-position) t)
1479 (current-column))))
1480
1481 (defun markdown-prev-line-indent ()
1482 "Return the number of leading whitespace characters in the previous line."
1483 (save-excursion
1484 (forward-line -1)
1485 (markdown-cur-line-indent)))
1486
1487 (defun markdown-next-line-indent ()
1488 "Return the number of leading whitespace characters in the next line."
1489 (save-excursion
1490 (forward-line 1)
1491 (markdown-cur-line-indent)))
1492
1493 (defun markdown-cur-non-list-indent ()
1494 "Return beginning position of list item text (not including the list marker).
1495 Return nil if the current line is not the beginning of a list item."
1496 (save-match-data
1497 (save-excursion
1498 (beginning-of-line)
1499 (when (re-search-forward markdown-regex-list (line-end-position) t)
1500 (current-column)))))
1501
1502 (defun markdown-prev-non-list-indent ()
1503 "Return position of the first non-list-marker on the previous line."
1504 (save-excursion
1505 (forward-line -1)
1506 (markdown-cur-non-list-indent)))
1507
1508 (defun markdown-new-baseline-p ()
1509 "Determine if the current line begins a new baseline level."
1510 (save-excursion
1511 (beginning-of-line)
1512 (save-match-data
1513 (or (looking-at markdown-regex-header)
1514 (looking-at markdown-regex-hr)
1515 (and (null (markdown-cur-non-list-indent))
1516 (= (markdown-cur-line-indent) 0)
1517 (markdown-prev-line-blank-p))))))
1518
1519 (defun markdown-search-backward-baseline ()
1520 "Search backward baseline point with no indentation and not a list item."
1521 (end-of-line)
1522 (let (stop)
1523 (while (not (or stop (bobp)))
1524 (re-search-backward markdown-regex-block-separator nil t)
1525 (when (match-end 2)
1526 (goto-char (match-end 2))
1527 (cond
1528 ((markdown-new-baseline-p)
1529 (setq stop t))
1530 ((looking-at markdown-regex-list)
1531 (setq stop nil))
1532 (t (setq stop t)))))))
1533
1534 (defun markdown-update-list-levels (marker indent levels)
1535 "Update list levels given list MARKER, block INDENT, and current LEVELS.
1536 Here, MARKER is a string representing the type of list, INDENT is an integer
1537 giving the indentation, in spaces, of the current block, and LEVELS is a
1538 list of the indentation levels of parent list items. When LEVELS is nil,
1539 it means we are at baseline (not inside of a nested list)."
1540 (cond
1541 ;; New list item at baseline.
1542 ((and marker (null levels))
1543 (setq levels (list indent)))
1544 ;; List item with greater indentation (four or more spaces).
1545 ;; Increase list level.
1546 ((and marker (>= indent (+ (car levels) 4)))
1547 (setq levels (cons indent levels)))
1548 ;; List item with greater or equal indentation (less than four spaces).
1549 ;; Do not increase list level.
1550 ((and marker (>= indent (car levels)))
1551 levels)
1552 ;; Lesser indentation level.
1553 ;; Pop appropriate number of elements off LEVELS list (e.g., lesser
1554 ;; indentation could move back more than one list level). Note
1555 ;; that this block need not be the beginning of list item.
1556 ((< indent (car levels))
1557 (while (and (> (length levels) 1)
1558 (< indent (+ (cadr levels) 4)))
1559 (setq levels (cdr levels)))
1560 levels)
1561 ;; Otherwise, do nothing.
1562 (t levels)))
1563
1564 (defun markdown-calculate-list-levels ()
1565 "Calculate list levels at point.
1566 Return a list of the form (n1 n2 n3 ...) where n1 is the
1567 indentation of the deepest nested list item in the branch of
1568 the list at the point, n2 is the indentation of the parent
1569 list item, and so on. The depth of the list item is therefore
1570 the length of the returned list. If the point is not at or
1571 immediately after a list item, return nil."
1572 (save-excursion
1573 (let ((first (point)) levels indent pre-regexp)
1574 ;; Find a baseline point with zero list indentation
1575 (markdown-search-backward-baseline)
1576 ;; Search for all list items between baseline and LOC
1577 (while (and (< (point) first)
1578 (re-search-forward markdown-regex-list first t))
1579 (setq pre-regexp (format "^\\( \\|\t\\)\\{%d\\}" (1+ (length levels))))
1580 (beginning-of-line)
1581 (cond
1582 ;; Make sure this is not a header or hr
1583 ((markdown-new-baseline-p) (setq levels nil))
1584 ;; Make sure this is not a line from a pre block
1585 ((looking-at pre-regexp))
1586 ;; If not, then update levels
1587 (t
1588 (setq indent (markdown-cur-line-indent))
1589 (setq levels (markdown-update-list-levels (match-string 2)
1590 indent levels))))
1591 (end-of-line))
1592 levels)))
1593
1594 (defun markdown-prev-list-item (level)
1595 "Search backward from point for a list item with indentation LEVEL.
1596 Set point to the beginning of the item, and return point, or nil
1597 upon failure."
1598 (let (bounds indent prev)
1599 (setq prev (point))
1600 (forward-line -1)
1601 (setq indent (markdown-cur-line-indent))
1602 (while
1603 (cond
1604 ;; Stop at beginning of buffer
1605 ((bobp) (setq prev nil))
1606 ;; Continue if current line is blank
1607 ((markdown-cur-line-blank-p) t)
1608 ;; List item
1609 ((and (looking-at markdown-regex-list)
1610 (setq bounds (markdown-cur-list-item-bounds)))
1611 (cond
1612 ;; Continue at item with greater indentation
1613 ((> (nth 3 bounds) level) t)
1614 ;; Stop and return point at item of equal indentation
1615 ((= (nth 3 bounds) level)
1616 (setq prev (point))
1617 nil)
1618 ;; Stop and return nil at item with lesser indentation
1619 ((< (nth 3 bounds) level)
1620 (setq prev nil)
1621 nil)))
1622 ;; Continue while indentation is the same or greater
1623 ((>= indent level) t)
1624 ;; Stop if current indentation is less than list item
1625 ;; and the next is blank
1626 ((and (< indent level)
1627 (markdown-next-line-blank-p))
1628 (setq prev nil))
1629 ;; Stop at a header
1630 ((looking-at markdown-regex-header) (setq prev nil))
1631 ;; Stop at a horizontal rule
1632 ((looking-at markdown-regex-hr) (setq prev nil))
1633 ;; Otherwise, continue.
1634 (t t))
1635 (forward-line -1)
1636 (setq indent (markdown-cur-line-indent)))
1637 prev))
1638
1639 (defun markdown-next-list-item (level)
1640 "Search forward from point for the next list item with indentation LEVEL.
1641 Set point to the beginning of the item, and return point, or nil
1642 upon failure."
1643 (let (bounds indent prev next)
1644 (setq next (point))
1645 (forward-line)
1646 (setq indent (markdown-cur-line-indent))
1647 (while
1648 (cond
1649 ;; Stop at end of the buffer.
1650 ((eobp) (setq prev nil))
1651 ;; Continue if the current line is blank
1652 ((markdown-cur-line-blank-p) t)
1653 ;; List item
1654 ((and (looking-at markdown-regex-list)
1655 (setq bounds (markdown-cur-list-item-bounds)))
1656 (cond
1657 ;; Continue at item with greater indentation
1658 ((> (nth 3 bounds) level) t)
1659 ;; Stop and return point at item of equal indentation
1660 ((= (nth 3 bounds) level)
1661 (setq next (point))
1662 nil)
1663 ;; Stop and return nil at item with lesser indentation
1664 ((< (nth 3 bounds) level)
1665 (setq next nil)
1666 nil)))
1667 ;; Continue while indentation is the same or greater
1668 ((>= indent level) t)
1669 ;; Stop if current indentation is less than list item
1670 ;; and the previous line was blank.
1671 ((and (< indent level)
1672 (markdown-prev-line-blank-p))
1673 (setq next nil))
1674 ;; Stop at a header
1675 ((looking-at markdown-regex-header) (setq next nil))
1676 ;; Stop at a horizontal rule
1677 ((looking-at markdown-regex-hr) (setq next nil))
1678 ;; Otherwise, continue.
1679 (t t))
1680 (forward-line)
1681 (setq indent (markdown-cur-line-indent)))
1682 next))
1683
1684 (defun markdown-cur-list-item-end (level)
1685 "Move to the end of the current list item with nonlist indentation LEVEL.
1686 If the point is not in a list item, do nothing."
1687 (let (indent)
1688 (forward-line)
1689 (setq indent (markdown-cur-line-indent))
1690 (while
1691 (cond
1692 ;; Stop at end of the buffer.
1693 ((eobp) nil)
1694 ;; Continue if the current line is blank
1695 ((markdown-cur-line-blank-p) t)
1696 ;; Continue while indentation is the same or greater
1697 ((>= indent level) t)
1698 ;; Stop if current indentation is less than list item
1699 ;; and the previous line was blank.
1700 ((and (< indent level)
1701 (markdown-prev-line-blank-p))
1702 nil)
1703 ;; Stop at a new list item of the same or lesser indentation
1704 ((looking-at markdown-regex-list) nil)
1705 ;; Stop at a header
1706 ((looking-at markdown-regex-header) nil)
1707 ;; Stop at a horizontal rule
1708 ((looking-at markdown-regex-hr) nil)
1709 ;; Otherwise, continue.
1710 (t t))
1711 (forward-line)
1712 (setq indent (markdown-cur-line-indent)))
1713 ;; Don't skip over whitespace for empty list items (marker and
1714 ;; whitespace only), just move to end of whitespace.
1715 (if (looking-back (concat markdown-regex-list "\\s-*"))
1716 (goto-char (match-end 3))
1717 (skip-syntax-backward "-"))))
1718
1719 (defun markdown-cur-list-item-bounds ()
1720 "Return bounds and indentation of the current list item.
1721 Return a list of the form (begin end indent nonlist-indent marker).
1722 If the point is not inside a list item, return nil.
1723 Leave match data intact for `markdown-regex-list'."
1724 (let (cur prev-begin prev-end indent nonlist-indent marker)
1725 ;; Store current location
1726 (setq cur (point))
1727 ;; Verify that cur is between beginning and end of item
1728 (save-excursion
1729 (end-of-line)
1730 (when (re-search-backward markdown-regex-list nil t)
1731 (setq prev-begin (match-beginning 0))
1732 (setq indent (length (match-string 1)))
1733 (setq nonlist-indent (length (match-string 0)))
1734 (setq marker (concat (match-string 2) (match-string 3)))
1735 (save-match-data
1736 (markdown-cur-list-item-end nonlist-indent)
1737 (setq prev-end (point)))
1738 (when (and (>= cur prev-begin)
1739 (<= cur prev-end)
1740 nonlist-indent)
1741 (list prev-begin prev-end indent nonlist-indent marker))))))
1742
1743 (defun markdown-bounds-of-thing-at-point (thing)
1744 "Call `bounds-of-thing-at-point' for THING with slight modifications.
1745 Does not include trailing newlines when THING is 'line. Handles the
1746 end of buffer case by setting both endpoints equal to the value of
1747 `point-max', since an empty region will trigger empty markup insertion.
1748 Return bounds of form (beg . end) if THING is found, or nil otherwise."
1749 (let* ((bounds (bounds-of-thing-at-point thing))
1750 (a (car bounds))
1751 (b (cdr bounds)))
1752 (when bounds
1753 (when (eq thing 'line)
1754 (cond ((and (eobp) (markdown-cur-line-blank-p))
1755 (setq a b))
1756 ((char-equal (char-before b) ?\^J)
1757 (setq b (1- b)))))
1758 (cons a b))))
1759
1760 (defun markdown-reference-definition (reference)
1761 "Find out whether Markdown REFERENCE is defined.
1762 REFERENCE should include the square brackets, like [this].
1763 When REFERENCE is defined, return a list of the form (text start end)
1764 containing the definition text itself followed by the start and end
1765 locations of the text. Otherwise, return nil.
1766 Leave match data for `markdown-regex-reference-definition'
1767 intact additional processing."
1768 (let ((reference (downcase reference)))
1769 (save-excursion
1770 (goto-char (point-min))
1771 (catch 'found
1772 (while (re-search-forward markdown-regex-reference-definition nil t)
1773 (when (string= reference (downcase (match-string-no-properties 1)))
1774 (throw 'found
1775 (list (match-string-no-properties 2)
1776 (match-beginning 2) (match-end 2)))))))))
1777
1778 (defun markdown-get-defined-references ()
1779 "Return a list of all defined reference labels (including square brackets)."
1780 (save-excursion
1781 (goto-char (point-min))
1782 (let (refs)
1783 (while (re-search-forward markdown-regex-reference-definition nil t)
1784 (let ((target (match-string-no-properties 1)))
1785 (add-to-list 'refs target t)))
1786 refs)))
1787
1788 (defun markdown-code-at-point-p ()
1789 "Return non-nil if the point is at an inline code fragment.
1790 Return nil otherwise. Set match data according to
1791 `markdown-match-code' upon success.
1792 This function searches the block for a code fragment that
1793 contains the point using `markdown-match-code'. We do this
1794 because `thing-at-point-looking-at' does not work reliably with
1795 `markdown-regex-code'."
1796 (interactive)
1797 (save-excursion
1798 (let ((old-point (point))
1799 (end-of-block (progn (markdown-end-of-block) (point)))
1800 found)
1801 (markdown-beginning-of-block)
1802 (while (and (markdown-match-code end-of-block)
1803 (setq found t)
1804 (< (match-end 0) old-point)))
1805 (and found ; matched something
1806 (<= (match-beginning 0) old-point) ; match contains old-point
1807 (>= (match-end 0) old-point)))))
1808
1809 \f
1810 ;;; Markdown Font Lock Matching Functions =====================================
1811
1812 (defun markdown-match-comments (last)
1813 "Match HTML comments from the point to LAST."
1814 (cond ((search-forward "<!--" last t)
1815 (backward-char 4)
1816 (let ((beg (point)))
1817 (cond ((search-forward-regexp "--[ \t]*>" last t)
1818 (set-match-data (list beg (point)))
1819 t)
1820 (t nil))))
1821 (t nil)))
1822
1823 (defun markdown-match-code (last)
1824 "Match inline code from the point to LAST."
1825 (unless (bobp)
1826 (backward-char 1))
1827 (cond ((re-search-forward markdown-regex-code last t)
1828 (set-match-data (list (match-beginning 2) (match-end 2)
1829 (match-beginning 4) (match-end 4)))
1830 (goto-char (match-end 0))
1831 t)
1832 (t (forward-char 2) nil)))
1833
1834 (defun markdown-match-pre-blocks (last)
1835 "Match Markdown pre blocks from point to LAST."
1836 (let ((levels (markdown-calculate-list-levels))
1837 indent pre-regexp end-regexp begin end stop)
1838 (while (and (< (point) last) (not end))
1839 ;; Search for a region with sufficient indentation
1840 (if (null levels)
1841 (setq indent 1)
1842 (setq indent (1+ (length levels))))
1843 (setq pre-regexp (format "^\\( \\|\t\\)\\{%d\\}" indent))
1844 (setq end-regexp (format "^\\( \\|\t\\)\\{0,%d\\}\\([^ \t]\\)" (1- indent)))
1845
1846 (cond
1847 ;; If not at the beginning of a line, move forward
1848 ((not (bolp)) (forward-line))
1849 ;; Move past blank lines
1850 ((markdown-cur-line-blank-p) (forward-line))
1851 ;; At headers and horizontal rules, reset levels
1852 ((markdown-new-baseline-p) (forward-line) (setq levels nil))
1853 ;; If the current line has sufficient indentation, mark out pre block
1854 ((looking-at pre-regexp)
1855 (setq begin (match-beginning 0))
1856 (while (and (or (looking-at pre-regexp) (markdown-cur-line-blank-p))
1857 (not (eobp)))
1858 (forward-line))
1859 (setq end (point)))
1860 ;; If current line has a list marker, update levels, move to end of block
1861 ((looking-at markdown-regex-list)
1862 (setq levels (markdown-update-list-levels
1863 (match-string 2) (markdown-cur-line-indent) levels))
1864 (markdown-end-of-block-element))
1865 ;; If this is the end of the indentation level, adjust levels accordingly.
1866 ;; Only match end of indentation level if levels is not the empty list.
1867 ((and (car levels) (looking-at end-regexp))
1868 (setq levels (markdown-update-list-levels
1869 nil (markdown-cur-line-indent) levels))
1870 (markdown-end-of-block-element))
1871 (t (markdown-end-of-block-element))))
1872
1873 (if (not (and begin end))
1874 ;; Return nil if no pre block was found
1875 nil
1876 ;; Set match data and return t upon success
1877 (set-match-data (list begin end))
1878 t)))
1879
1880 (defun markdown-match-fenced-code-blocks (last)
1881 "Match fenced code blocks from the point to LAST."
1882 (cond ((search-forward-regexp "^\\([~]\\{3,\\}\\)" last t)
1883 (beginning-of-line)
1884 (let ((beg (point)))
1885 (forward-line)
1886 (cond ((search-forward-regexp
1887 (concat "^" (match-string 1) "~*") last t)
1888 (set-match-data (list beg (point)))
1889 t)
1890 (t nil))))
1891 (t nil)))
1892
1893 (defun markdown-match-gfm-code-blocks (last)
1894 "Match GFM quoted code blocks from point to LAST."
1895 (let (open lang body close all)
1896 (cond ((and (eq major-mode 'gfm-mode)
1897 (search-forward-regexp "^\\(```\\)\\([^[:space:]]+[[:space:]]*\\)?$" last t))
1898 (beginning-of-line)
1899 (setq open (list (match-beginning 1) (match-end 1))
1900 lang (list (match-beginning 2) (match-end 2)))
1901 (forward-line)
1902 (setq body (list (point)))
1903 (cond ((search-forward-regexp "^```$" last t)
1904 (setq body (reverse (cons (1- (match-beginning 0)) body))
1905 close (list (match-beginning 0) (match-end 0))
1906 all (list (car open) (match-end 0)))
1907 (set-match-data (append all open lang body close))
1908 t)
1909 (t nil)))
1910 (t nil))))
1911
1912 (defun markdown-match-generic-metadata (regexp last)
1913 "Match generic metadata specified by REGEXP from the point to LAST."
1914 (let ((header-end (save-excursion
1915 (goto-char (point-min))
1916 (if (re-search-forward "\n\n" (point-max) t)
1917 (match-beginning 0)
1918 (point-max)))))
1919 (cond ((>= (point) header-end)
1920 ;; Don't match anything outside of the header.
1921 nil)
1922 ((re-search-forward regexp (min last header-end) t)
1923 ;; If a metadata item is found, it may span several lines.
1924 (let ((key-beginning (match-beginning 1))
1925 (key-end (match-end 1))
1926 (value-beginning (match-beginning 2)))
1927 (while (and (not (looking-at regexp))
1928 (not (> (point) (min last header-end)))
1929 (not (eobp)))
1930 (forward-line))
1931 (unless (eobp)
1932 (forward-line -1)
1933 (end-of-line))
1934 (set-match-data (list key-beginning (point) ; complete metadata
1935 key-beginning key-end ; key
1936 value-beginning (point))) ; value
1937 t))
1938 (t nil))))
1939
1940 (defun markdown-match-multimarkdown-metadata (last)
1941 "Match MultiMarkdown metadata from the point to LAST."
1942 (markdown-match-generic-metadata markdown-regex-multimarkdown-metadata last))
1943
1944 (defun markdown-match-pandoc-metadata (last)
1945 "Match Pandoc metadata from the point to LAST."
1946 (markdown-match-generic-metadata markdown-regex-pandoc-metadata last))
1947
1948 (defun markdown-font-lock-extend-region ()
1949 "Extend the search region to include an entire block of text.
1950 This helps improve font locking for block constructs such as pre blocks."
1951 ;; Avoid compiler warnings about these global variables from font-lock.el.
1952 ;; See the documentation for variable `font-lock-extend-region-functions'.
1953 (eval-when-compile (defvar font-lock-beg) (defvar font-lock-end))
1954 (save-excursion
1955 (goto-char font-lock-beg)
1956 (unless (looking-back "\n\n")
1957 (let ((found (or (re-search-backward "\n\n" nil t) (point-min))))
1958 (goto-char font-lock-end)
1959 (when (re-search-forward "\n\n" nil t)
1960 (setq font-lock-end (match-beginning 0))
1961 (setq font-lock-beg found))))))
1962
1963 \f
1964 ;;; Syntax Table ==============================================================
1965
1966 (defvar markdown-mode-syntax-table
1967 (let ((tab (make-syntax-table text-mode-syntax-table)))
1968 (modify-syntax-entry ?\" "." tab)
1969 tab)
1970 "Syntax table for `markdown-mode'.")
1971
1972 \f
1973 ;;; Element Insertion =========================================================
1974
1975 (defun markdown-ensure-blank-line-before ()
1976 "If previous line is not already blank, insert a blank line before point."
1977 (unless (bolp) (insert "\n"))
1978 (unless (or (bobp) (looking-back "\n\\s-*\n")) (insert "\n")))
1979
1980 (defun markdown-ensure-blank-line-after ()
1981 "If following line is not already blank, insert a blank line after point.
1982 Return the point where it was originally."
1983 (save-excursion
1984 (unless (eolp) (insert "\n"))
1985 (unless (or (eobp) (looking-at "\n\\s-*\n")) (insert "\n"))))
1986
1987 (defun markdown-wrap-or-insert (s1 s2 &optional thing beg end)
1988 "Insert the strings S1 and S2, wrapping around region or THING.
1989 If a region is specified by the optional BEG and END arguments,
1990 wrap the strings S1 and S2 around that region.
1991 If there is an active region, wrap the strings S1 and S2 around
1992 the region. If there is not an active region but the point is at
1993 THING, wrap that thing (which defaults to word). Otherwise, just
1994 insert S1 and S2 and place the cursor in between. Return the
1995 bounds of the entire wrapped string, or nil if nothing was wrapped
1996 and S1 and S2 were only inserted."
1997 (let (a b bounds new-point)
1998 (cond
1999 ;; Given region
2000 ((and beg end)
2001 (setq a beg
2002 b end
2003 new-point (+ (point) (length s1))))
2004 ;; Active region
2005 ((markdown-use-region-p)
2006 (setq a (region-beginning)
2007 b (region-end)
2008 new-point (+ (point) (length s1))))
2009 ;; Thing (word) at point
2010 ((setq bounds (markdown-bounds-of-thing-at-point (or thing 'word)))
2011 (setq a (car bounds)
2012 b (cdr bounds)
2013 new-point (+ (point) (length s1))))
2014 ;; No active region and no word
2015 (t
2016 (setq a (point)
2017 b (point))))
2018 (goto-char b)
2019 (insert s2)
2020 (goto-char a)
2021 (insert s1)
2022 (when new-point (goto-char new-point))
2023 (if (= a b)
2024 nil
2025 (setq b (+ b (length s1) (length s2)))
2026 (cons a b))))
2027
2028 (defun markdown-point-after-unwrap (cur prefix suffix)
2029 "Return desired position of point after an unwrapping operation.
2030 CUR gives the position of the point before the operation.
2031 Additionally, two cons cells must be provided. PREFIX gives the
2032 bounds of the prefix string and SUFFIX gives the bounds of the
2033 suffix string."
2034 (cond ((< cur (cdr prefix)) (car prefix))
2035 ((< cur (car suffix)) (- cur (- (cdr prefix) (car prefix))))
2036 ((<= cur (cdr suffix))
2037 (- cur (+ (- (cdr prefix) (car prefix))
2038 (- cur (car suffix)))))
2039 (t cur)))
2040
2041 (defun markdown-unwrap-thing-at-point (regexp all text)
2042 "Remove prefix and suffix of thing at point and reposition the point.
2043 When the thing at point matches REGEXP, replace the subexpression
2044 ALL with the string in subexpression TEXT. Reposition the point
2045 in an appropriate location accounting for the removal of prefix
2046 and suffix strings. Return new bounds of string from group TEXT.
2047 When REGEXP is nil, assumes match data is already set."
2048 (when (or (null regexp)
2049 (thing-at-point-looking-at regexp))
2050 (let ((cur (point))
2051 (prefix (cons (match-beginning all) (match-beginning text)))
2052 (suffix (cons (match-end text) (match-end all)))
2053 (bounds (cons (match-beginning text) (match-end text))))
2054 ;; Replace the thing at point
2055 (replace-match (match-string text) t t nil all)
2056 ;; Reposition the point
2057 (goto-char (markdown-point-after-unwrap cur prefix suffix))
2058 ;; Adjust bounds
2059 (setq bounds (cons (car prefix)
2060 (- (cdr bounds) (- (cdr prefix) (car prefix))))))))
2061
2062 (defun markdown-unwrap-things-in-region (beg end regexp all text)
2063 "Remove prefix and suffix of all things in region from BEG to END.
2064 When a thing in the region matches REGEXP, replace the
2065 subexpression ALL with the string in subexpression TEXT.
2066 Return a cons cell containing updated bounds for the region."
2067 (save-excursion
2068 (goto-char beg)
2069 (let ((removed 0) len-all len-text)
2070 (while (re-search-forward regexp (- end removed) t)
2071 (setq len-all (length (match-string-no-properties all)))
2072 (setq len-text (length (match-string-no-properties text)))
2073 (setq removed (+ removed (- len-all len-text)))
2074 (replace-match (match-string text) t t nil all))
2075 (cons beg (- end removed)))))
2076
2077 (defun markdown-insert-hr (arg)
2078 "Insert or replace a horizonal rule.
2079 By default, use the first element of `markdown-hr-strings'. When
2080 ARG is non-nil, as when given a prefix, select a different
2081 element as follows. When prefixed with \\[universal-argument],
2082 use the last element of `markdown-hr-strings' instead. When
2083 prefixed with an integer from 1 to the length of
2084 `markdown-hr-strings', use the element in that position instead."
2085 (interactive "*P")
2086 (when (thing-at-point-looking-at markdown-regex-hr)
2087 (delete-region (match-beginning 0) (match-end 0)))
2088 (markdown-ensure-blank-line-before)
2089 (cond ((equal arg '(4))
2090 (insert (car (reverse markdown-hr-strings))))
2091 ((and (integerp arg) (> arg 0)
2092 (<= arg (length markdown-hr-strings)))
2093 (insert (nth (1- arg) markdown-hr-strings)))
2094 (t
2095 (insert (car markdown-hr-strings))))
2096 (markdown-ensure-blank-line-after))
2097
2098 (defun markdown-insert-bold ()
2099 "Insert markup to make a region or word bold.
2100 If there is an active region, make the region bold. If the point
2101 is at a non-bold word, make the word bold. If the point is at a
2102 bold word or phrase, remove the bold markup. Otherwise, simply
2103 insert bold delimiters and place the cursor in between them."
2104 (interactive)
2105 (let ((delim (if markdown-bold-underscore "__" "**")))
2106 (if (markdown-use-region-p)
2107 ;; Active region
2108 (let ((bounds (markdown-unwrap-things-in-region
2109 (region-beginning) (region-end)
2110 markdown-regex-bold 2 4)))
2111 (markdown-wrap-or-insert delim delim nil (car bounds) (cdr bounds)))
2112 ;; Bold markup removal, bold word at point, or empty markup insertion
2113 (if (thing-at-point-looking-at markdown-regex-bold)
2114 (markdown-unwrap-thing-at-point nil 2 4)
2115 (markdown-wrap-or-insert delim delim 'word nil nil)))))
2116
2117 (defun markdown-insert-italic ()
2118 "Insert markup to make a region or word italic.
2119 If there is an active region, make the region italic. If the point
2120 is at a non-italic word, make the word italic. If the point is at an
2121 italic word or phrase, remove the italic markup. Otherwise, simply
2122 insert italic delimiters and place the cursor in between them."
2123 (interactive)
2124 (let ((delim (if markdown-italic-underscore "_" "*")))
2125 (if (markdown-use-region-p)
2126 ;; Active region
2127 (let ((bounds (markdown-unwrap-things-in-region
2128 (region-beginning) (region-end)
2129 markdown-regex-italic 2 4)))
2130 (markdown-wrap-or-insert delim delim nil (car bounds) (cdr bounds)))
2131 ;; Italic markup removal, italic word at point, or empty markup insertion
2132 (if (thing-at-point-looking-at markdown-regex-italic)
2133 (markdown-unwrap-thing-at-point nil 2 4)
2134 (markdown-wrap-or-insert delim delim 'word nil nil)))))
2135
2136 (defun markdown-insert-code ()
2137 "Insert markup to make a region or word an inline code fragment.
2138 If there is an active region, make the region an inline code
2139 fragment. If the point is at a word, make the word an inline
2140 code fragment. Otherwise, simply insert code delimiters and
2141 place the cursor in between them."
2142 (interactive)
2143 (if (markdown-use-region-p)
2144 ;; Active region
2145 (let ((bounds (markdown-unwrap-things-in-region
2146 (region-beginning) (region-end)
2147 markdown-regex-code 2 4)))
2148 (markdown-wrap-or-insert "`" "`" nil (car bounds) (cdr bounds)))
2149 ;; Code markup removal, code markup for word, or empty markup insertion
2150 (if (markdown-code-at-point-p)
2151 (markdown-unwrap-thing-at-point nil 0 1)
2152 (markdown-wrap-or-insert "`" "`" 'word nil nil))))
2153
2154 (defun markdown-insert-link ()
2155 "Insert an inline link, using region or word as link text if possible.
2156 If there is an active region, use the region as the link text. If the
2157 point is at a word, use the word as the link text. In these cases, the
2158 point will be left at the position for inserting a URL. If there is no
2159 active region and the point is not at word, simply insert link markup and
2160 place the point in the position to enter link text."
2161 (interactive)
2162 (let ((bounds (markdown-wrap-or-insert "[" "]()")))
2163 (when bounds
2164 (goto-char (- (cdr bounds) 1)))))
2165
2166 (defun markdown-insert-reference-link (text label &optional url title)
2167 "Insert a reference link and, optionally, a reference definition.
2168 The link TEXT will be inserted followed by the optional LABEL.
2169 If a URL is given, also insert a definition for the reference
2170 LABEL according to `markdown-reference-location'. If a TITLE is
2171 given, it will be added to the end of the reference definition
2172 and will be used to populate the title attribute when converted
2173 to XHTML. If URL is nil, insert only the link portion (for
2174 example, when a reference label is already defined)."
2175 (insert (concat "[" text "][" label "]"))
2176 (when url
2177 (let ((end (point))
2178 (label (if (> (length label) 0) label text)))
2179 (cond
2180 ((eq markdown-reference-location 'end) (goto-char (point-max)))
2181 ((eq markdown-reference-location 'immediately) (markdown-end-of-block))
2182 ((eq markdown-reference-location 'header) (markdown-end-of-defun)))
2183 (unless (markdown-cur-line-blank-p) (insert "\n"))
2184 (insert "\n[" label "]: " url)
2185 (unless (> (length url) 0)
2186 (setq end (point)))
2187 (when (> (length title) 0)
2188 (insert " \"" title "\""))
2189 (insert "\n")
2190 (unless (or (eobp) (looking-at "\n"))
2191 (insert "\n"))
2192 (goto-char end)
2193 (when (> (length url) 0)
2194 (message
2195 (substitute-command-keys
2196 "Defined reference [%s], press \\[markdown-jump] to jump there")
2197 (or label text))))))
2198
2199 (defun markdown-insert-reference-link-dwim ()
2200 "Insert a reference link of the form [text][label] at point.
2201 If there is an active region, the text in the region will be used
2202 as the link text. If the point is at a word, it will be used as
2203 the link text. Otherwise, the link text will be read from the
2204 minibuffer. The link label will be read from the minibuffer in
2205 both cases, with completion from the set of currently defined
2206 references. To create an implicit reference link, press RET to
2207 accept the default, an empty label. If the entered referenced
2208 label is not defined, additionally prompt for the URL
2209 and (optional) title. The reference definition is placed at the
2210 location determined by `markdown-reference-location'."
2211 (interactive)
2212 (let* ((defined-labels (mapcar (lambda (x) (substring x 1 -1))
2213 (markdown-get-defined-references)))
2214 (bounds (or (and (markdown-use-region-p)
2215 (cons (region-beginning) (region-end)))
2216 (markdown-bounds-of-thing-at-point 'word)))
2217 (text (if bounds
2218 (buffer-substring (car bounds) (cdr bounds))
2219 (read-string "Link Text: ")))
2220 (label (completing-read
2221 "Link Label (default: none): " defined-labels
2222 nil nil nil 'markdown-reference-label-history nil))
2223 (ref (markdown-reference-definition
2224 (concat "[" (if (> (length label) 0) label text) "]")))
2225 (url (unless ref (read-string "Link URL: ")))
2226 (title (when (> (length url) 0)
2227 (read-string "Link Title (optional): "))))
2228 (when bounds (delete-region (car bounds) (cdr bounds)))
2229 (markdown-insert-reference-link text label url title)))
2230
2231 (defun markdown-insert-uri ()
2232 "Insert markup for an inline URI.
2233 If there is an active region, use it as the URI. If the point is
2234 at a URI, wrap it with angle brackets. If the point is at an
2235 inline URI, remove the angle brackets. Otherwise, simply insert
2236 angle brackets place the point between them."
2237 (interactive)
2238 (if (markdown-use-region-p)
2239 ;; Active region
2240 (let ((bounds (markdown-unwrap-things-in-region
2241 (region-beginning) (region-end)
2242 markdown-regex-angle-uri 0 2)))
2243 (markdown-wrap-or-insert "<" ">" nil (car bounds) (cdr bounds)))
2244 ;; Markup removal, URI at point, or empty markup insertion
2245 (if (thing-at-point-looking-at markdown-regex-angle-uri)
2246 (markdown-unwrap-thing-at-point nil 0 2)
2247 (markdown-wrap-or-insert "<" ">" 'url nil nil))))
2248
2249 (defun markdown-insert-wiki-link ()
2250 "Insert a wiki link of the form [[WikiLink]].
2251 If there is an active region, use the region as the link text.
2252 If the point is at a word, use the word as the link text. If
2253 there is no active region and the point is not at word, simply
2254 insert link markup."
2255 (interactive)
2256 (if (markdown-use-region-p)
2257 ;; Active region
2258 (markdown-wrap-or-insert "[[" "]]" nil (region-beginning) (region-end))
2259 ;; Markup removal, wiki link at at point, or empty markup insertion
2260 (if (thing-at-point-looking-at markdown-regex-wiki-link)
2261 (if (or markdown-wiki-link-alias-first
2262 (null (match-string 4)))
2263 (markdown-unwrap-thing-at-point nil 1 2)
2264 (markdown-unwrap-thing-at-point nil 1 4))
2265 (markdown-wrap-or-insert "[[" "]]"))))
2266
2267 (defun markdown-insert-image (&optional arg)
2268 "Insert image markup using region or word as alt text if possible.
2269 If there is an active region, use the region as the alt text. If the
2270 point is at a word, use the word as the alt text. In these cases, the
2271 point will be left at the position for inserting a URL. If there is no
2272 active region and the point is not at word, simply insert image markup and
2273 place the point in the position to enter alt text. If ARG is nil, insert
2274 inline image markup. Otherwise, insert reference image markup."
2275 (interactive "*P")
2276 (let ((bounds (if arg
2277 (markdown-wrap-or-insert "![" "][]")
2278 (markdown-wrap-or-insert "![" "]()"))))
2279 (when bounds
2280 (goto-char (- (cdr bounds) 1)))))
2281
2282 (defun markdown-insert-reference-image ()
2283 "Insert reference-style image markup using region or word as alt text.
2284 Calls `markdown-insert-image' with prefix argument."
2285 (interactive)
2286 (markdown-insert-image t))
2287
2288 (defun markdown-remove-header ()
2289 "Remove header markup if point is at a header.
2290 Return bounds of remaining header text if a header was removed
2291 and nil otherwise."
2292 (interactive "*")
2293 (or (markdown-unwrap-thing-at-point markdown-regex-header-atx 0 2)
2294 (markdown-unwrap-thing-at-point markdown-regex-header-setext 0 1)))
2295
2296 (defun markdown-insert-header (&optional level text setext)
2297 "Insert or replace header markup.
2298 The level of the header is specified by LEVEL and header text is
2299 given by TEXT. LEVEL must be an integer from 1 and 6, and the
2300 default value is 1.
2301 When TEXT is nil, the header text is obtained as follows.
2302 If there is an active region, it is used as the header text.
2303 Otherwise, the current line will be used as the header text.
2304 If there is not an active region and the point is at a header,
2305 remove the header markup and replace with level N header.
2306 Otherwise, insert empty header markup and place the cursor in
2307 between.
2308 The style of the header will be atx (hash marks) unless
2309 SETEXT is non-nil, in which case a setext-style (underlined)
2310 header will be inserted."
2311 (interactive "p\nsHeader text: ")
2312 (setq level (min (max (or level 1) 1) (if setext 2 6)))
2313 ;; Determine header text if not given
2314 (when (null text)
2315 (if (markdown-use-region-p)
2316 ;; Active region
2317 (setq text (delete-and-extract-region (region-beginning) (region-end)))
2318 ;; No active region
2319 (markdown-remove-header)
2320 (setq text (delete-and-extract-region
2321 (line-beginning-position) (line-end-position)))
2322 (when (and setext (string-match "^[ \t]*$" text))
2323 (setq text (read-string "Header text: "))))
2324 (setq text (markdown-compress-whitespace-string text)))
2325 ;; Insertion with given text
2326 (markdown-ensure-blank-line-before)
2327 (let (hdr)
2328 (cond (setext
2329 (setq hdr (make-string (string-width text) (if (= level 2) ?- ?=)))
2330 (insert text "\n" hdr))
2331 (t
2332 (setq hdr (make-string level ?#))
2333 (insert hdr " " text " " hdr))))
2334 (markdown-ensure-blank-line-after)
2335 ;; Leave point at end of text
2336 (if setext
2337 (backward-char (1+ (string-width text)))
2338 (backward-char (1+ level))))
2339
2340 (defun markdown-insert-header-dwim (&optional arg setext)
2341 "Insert or replace header markup.
2342 The level and type of the header are determined automatically by
2343 the type and level of the previous header, unless a prefix
2344 argument is given via ARG.
2345 With a numeric prefix valued 1 to 6, insert a header of the given
2346 level, with the type being determined automatically (note that
2347 only level 1 or 2 setext headers are possible).
2348
2349 With a \\[universal-argument] prefix (i.e., when ARG is (4)),
2350 promote the heading by one level.
2351 With two \\[universal-argument] prefixes (i.e., when ARG is (16)),
2352 demote the heading by one level.
2353 When SETEXT is non-nil, prefer setext-style headers when
2354 possible (levels one and two).
2355
2356 When there is an active region, use it for the header text. When
2357 the point is at an existing header, change the type and level
2358 according to the rules above.
2359 Otherwise, if the line is not empty, create a header using the
2360 text on the current line as the header text.
2361 Finally, if the point is on a blank line, insert empty header
2362 markup (atx) or prompt for text (setext).
2363 See `markdown-insert-header' for more details about how the
2364 header text is determined."
2365 (interactive "*P")
2366 (let (level)
2367 (save-excursion
2368 (when (re-search-backward markdown-regex-header nil t)
2369 ;; level of previous header
2370 (setq level (markdown-outline-level))
2371 ;; match groups 1 and 2 indicate setext headers
2372 (setq setext (or setext (match-end 1) (match-end 3)))))
2373 ;; check prefix argument
2374 (cond
2375 ((and (equal arg '(4)) (> level 1)) ;; C-u
2376 (decf level))
2377 ((and (equal arg '(16)) (< level 6)) ;; C-u C-u
2378 (incf level))
2379 (arg ;; numeric prefix
2380 (setq level (prefix-numeric-value arg))))
2381 ;; setext headers must be level one or two
2382 (and level (setq setext (and setext (<= level 2))))
2383 ;; insert the heading
2384 (markdown-insert-header level nil setext)))
2385
2386 (defun markdown-insert-header-setext-dwim (&optional arg)
2387 "Insert or replace header markup, with preference for setext.
2388 See `markdown-insert-header-dwim' for details, including how ARG is handled."
2389 (interactive "*P")
2390 (markdown-insert-header-dwim arg t))
2391
2392 (defun markdown-insert-header-atx-1 ()
2393 "Insert a first level atx-style (hash mark) header.
2394 See `markdown-insert-header'."
2395 (interactive "*")
2396 (markdown-insert-header 1 nil nil))
2397
2398 (defun markdown-insert-header-atx-2 ()
2399 "Insert a level two atx-style (hash mark) header.
2400 See `markdown-insert-header'."
2401 (interactive "*")
2402 (markdown-insert-header 2 nil nil))
2403
2404 (defun markdown-insert-header-atx-3 ()
2405 "Insert a level three atx-style (hash mark) header.
2406 See `markdown-insert-header'."
2407 (interactive "*")
2408 (markdown-insert-header 3 nil nil))
2409
2410 (defun markdown-insert-header-atx-4 ()
2411 "Insert a level four atx-style (hash mark) header.
2412 See `markdown-insert-header'."
2413 (interactive "*")
2414 (markdown-insert-header 4 nil nil))
2415
2416 (defun markdown-insert-header-atx-5 ()
2417 "Insert a level five atx-style (hash mark) header.
2418 See `markdown-insert-header'."
2419 (interactive "*")
2420 (markdown-insert-header 5 nil nil))
2421
2422 (defun markdown-insert-header-atx-6 ()
2423 "Insert a sixth level atx-style (hash mark) header.
2424 See `markdown-insert-header'."
2425 (interactive "*")
2426 (markdown-insert-header 6 nil nil))
2427
2428 (defun markdown-insert-header-setext-1 ()
2429 "Insert a setext-style (underlined) first-level header.
2430 See `markdown-insert-header'."
2431 (interactive "*")
2432 (markdown-insert-header 1 nil t))
2433
2434 (defun markdown-insert-header-setext-2 ()
2435 "Insert a setext-style (underlined) second-level header.
2436 See `markdown-insert-header'."
2437 (interactive "*")
2438 (markdown-insert-header 2 nil t))
2439
2440 (defun markdown-blockquote-indentation (loc)
2441 "Return string containing necessary indentation for a blockquote at LOC.
2442 Also see `markdown-pre-indentation'."
2443 (save-excursion
2444 (goto-char loc)
2445 (let* ((list-level (length (markdown-calculate-list-levels)))
2446 (indent ""))
2447 (dotimes (count list-level indent)
2448 (setq indent (concat indent " "))))))
2449
2450 (defun markdown-insert-blockquote ()
2451 "Start a blockquote section (or blockquote the region).
2452 If Transient Mark mode is on and a region is active, it is used as
2453 the blockquote text."
2454 (interactive)
2455 (if (markdown-use-region-p)
2456 (markdown-blockquote-region (region-beginning) (region-end))
2457 (markdown-ensure-blank-line-before)
2458 (insert (markdown-blockquote-indentation (point)) "> ")
2459 (markdown-ensure-blank-line-after)))
2460
2461 (defun markdown-block-region (beg end prefix)
2462 "Format the region using a block prefix.
2463 Arguments BEG and END specify the beginning and end of the
2464 region. The characters PREFIX will appear at the beginning
2465 of each line."
2466 (save-excursion
2467 (let* ((end-marker (make-marker))
2468 (beg-marker (make-marker)))
2469 ;; Ensure blank line after and remove extra whitespace
2470 (goto-char end)
2471 (skip-syntax-backward "-")
2472 (set-marker end-marker (point))
2473 (delete-horizontal-space)
2474 (markdown-ensure-blank-line-after)
2475 ;; Ensure blank line before and remove extra whitespace
2476 (goto-char beg)
2477 (skip-syntax-forward "-")
2478 (delete-horizontal-space)
2479 (markdown-ensure-blank-line-before)
2480 (set-marker beg-marker (point))
2481 ;; Insert PREFIX before each line
2482 (goto-char beg-marker)
2483 (while (and (< (line-beginning-position) end-marker)
2484 (not (eobp)))
2485 (insert prefix)
2486 (forward-line)))))
2487
2488 (defun markdown-blockquote-region (beg end)
2489 "Blockquote the region.
2490 Arguments BEG and END specify the beginning and end of the region."
2491 (interactive "*r")
2492 (markdown-block-region
2493 beg end (concat (markdown-blockquote-indentation
2494 (max (point-min) (1- beg))) "> ")))
2495
2496 (defun markdown-pre-indentation (loc)
2497 "Return string containing necessary whitespace for a pre block at LOC.
2498 Also see `markdown-blockquote-indentation'."
2499 (save-excursion
2500 (goto-char loc)
2501 (let* ((list-level (length (markdown-calculate-list-levels)))
2502 indent)
2503 (dotimes (count (1+ list-level) indent)
2504 (setq indent (concat indent " "))))))
2505
2506 (defun markdown-insert-pre ()
2507 "Start a preformatted section (or apply to the region).
2508 If Transient Mark mode is on and a region is active, it is marked
2509 as preformatted text."
2510 (interactive)
2511 (if (markdown-use-region-p)
2512 (markdown-pre-region (region-beginning) (region-end))
2513 (markdown-ensure-blank-line-before)
2514 (insert (markdown-pre-indentation (point)))
2515 (markdown-ensure-blank-line-after)))
2516
2517 (defun markdown-pre-region (beg end)
2518 "Format the region as preformatted text.
2519 Arguments BEG and END specify the beginning and end of the region."
2520 (interactive "*r")
2521 (let ((indent (markdown-pre-indentation (max (point-min) (1- beg)))))
2522 (markdown-block-region beg end indent)))
2523
2524 (defun markdown-insert-gfm-code-block (&optional lang)
2525 "Insert GFM code block for language LANG.
2526 If LANG is nil, the language will be queried from user. If a
2527 region is active, wrap this region with the markup instead. If
2528 the region boundaries are not on empty lines, these are added
2529 automatically in order to have the correct markup."
2530 (interactive "sProgramming language [none]: ")
2531 (if (markdown-use-region-p)
2532 (let ((b (region-beginning)) (e (region-end)))
2533 (goto-char e)
2534 ;; if we're on a blank line, don't newline, otherwise the ```
2535 ;; should go on its own line
2536 (unless (looking-back "\n")
2537 (newline))
2538 (insert "```")
2539 (markdown-ensure-blank-line-after)
2540 (goto-char b)
2541 ;; if we're on a blank line, insert the quotes here, otherwise
2542 ;; add a new line first
2543 (unless (looking-at "\n")
2544 (newline)
2545 (forward-line -1))
2546 (markdown-ensure-blank-line-before)
2547 (insert "```" lang))
2548 (markdown-ensure-blank-line-before)
2549 (insert "```" lang)
2550 (newline 2)
2551 (insert "```")
2552 (markdown-ensure-blank-line-after)
2553 (forward-line -1)))
2554
2555 \f
2556 ;;; Footnotes ======================================================================
2557
2558 (defun markdown-footnote-counter-inc ()
2559 "Increment `markdown-footnote-counter' and return the new value."
2560 (when (= markdown-footnote-counter 0) ; hasn't been updated in this buffer yet.
2561 (save-excursion
2562 (goto-char (point-min))
2563 (while (re-search-forward (concat "^\\[\\^\\(" markdown-footnote-chars "*?\\)\\]:")
2564 (point-max) t)
2565 (let ((fn (string-to-number (match-string 1))))
2566 (when (> fn markdown-footnote-counter)
2567 (setq markdown-footnote-counter fn))))))
2568 (incf markdown-footnote-counter))
2569
2570 (defun markdown-insert-footnote ()
2571 "Insert footnote with a new number and move point to footnote definition."
2572 (interactive)
2573 (let ((fn (markdown-footnote-counter-inc)))
2574 (insert (format "[^%d]" fn))
2575 (markdown-footnote-text-find-new-location)
2576 (markdown-ensure-blank-line-before)
2577 (unless (markdown-cur-line-blank-p)
2578 (insert "\n"))
2579 (insert (format "[^%d]: " fn))
2580 (markdown-ensure-blank-line-after)))
2581
2582 (defun markdown-footnote-text-find-new-location ()
2583 "Position the cursor at the proper location for a new footnote text."
2584 (cond
2585 ((eq markdown-footnote-location 'end) (goto-char (point-max)))
2586 ((eq markdown-footnote-location 'immediately) (markdown-end-of-block))
2587 ((eq markdown-footnote-location 'header) (markdown-end-of-defun))))
2588
2589 (defun markdown-footnote-kill ()
2590 "Kill the footnote at point.
2591 The footnote text is killed (and added to the kill ring), the
2592 footnote marker is deleted. Point has to be either at the
2593 footnote marker or in the footnote text."
2594 (interactive)
2595 (let (return-pos)
2596 (when (markdown-footnote-text-positions) ; if we're in a footnote text
2597 (markdown-footnote-return) ; we first move to the marker
2598 (setq return-pos 'text)) ; and remember our return position
2599 (let ((marker (markdown-footnote-delete-marker)))
2600 (unless marker
2601 (error "Not at a footnote"))
2602 (let ((text-pos (markdown-footnote-find-text (car marker))))
2603 (unless text-pos
2604 (error "No text for footnote `%s'" (car marker)))
2605 (goto-char text-pos)
2606 (let ((pos (markdown-footnote-kill-text)))
2607 (setq return-pos
2608 (if (and pos (eq return-pos 'text))
2609 pos
2610 (cadr marker))))))
2611 (goto-char return-pos)))
2612
2613 (defun markdown-footnote-delete-marker ()
2614 "Delete a footnote marker at point.
2615 Returns a list (ID START) containing the footnote ID and the
2616 start position of the marker before deletion. If no footnote
2617 marker was deleted, this function returns NIL."
2618 (let ((marker (markdown-footnote-marker-positions)))
2619 (when marker
2620 (delete-region (second marker) (third marker))
2621 (butlast marker))))
2622
2623 (defun markdown-footnote-kill-text ()
2624 "Kill footnote text at point.
2625 Returns the start position of the footnote text before deletion,
2626 or NIL if point was not inside a footnote text.
2627
2628 The killed text is placed in the kill ring (without the footnote
2629 number)."
2630 (let ((fn (markdown-footnote-text-positions)))
2631 (when fn
2632 (let ((text (delete-and-extract-region (second fn) (third fn))))
2633 (string-match (concat "\\[\\" (first fn) "\\]:[[:space:]]*\\(\\(.*\n?\\)*\\)") text)
2634 (kill-new (match-string 1 text))
2635 (when (and (markdown-cur-line-blank-p)
2636 (markdown-prev-line-blank-p))
2637 (delete-region (1- (point)) (point)))
2638 (second fn)))))
2639
2640 (defun markdown-footnote-goto-text ()
2641 "Jump to the text of the footnote at point."
2642 (interactive)
2643 (let ((fn (car (markdown-footnote-marker-positions))))
2644 (unless fn
2645 (error "Not at a footnote marker"))
2646 (let ((new-pos (markdown-footnote-find-text fn)))
2647 (unless new-pos
2648 (error "No definition found for footnote `%s'" fn))
2649 (goto-char new-pos))))
2650
2651 (defun markdown-footnote-return ()
2652 "Return from a footnote to its footnote number in the main text."
2653 (interactive)
2654 (let ((fn (save-excursion
2655 (car (markdown-footnote-text-positions)))))
2656 (unless fn
2657 (error "Not in a footnote"))
2658 (let ((new-pos (markdown-footnote-find-marker fn)))
2659 (unless new-pos
2660 (error "Footnote marker `%s' not found" fn))
2661 (goto-char new-pos))))
2662
2663 (defun markdown-footnote-find-marker (id)
2664 "Find the location of the footnote marker with ID.
2665 The actual buffer position returned is the position directly
2666 following the marker's closing bracket. If no marker is found,
2667 NIL is returned."
2668 (save-excursion
2669 (goto-char (point-min))
2670 (when (re-search-forward (concat "\\[" id "\\]\\([^:]\\|\\'\\)") nil t)
2671 (skip-chars-backward "^]")
2672 (point))))
2673
2674 (defun markdown-footnote-find-text (id)
2675 "Find the location of the text of footnote ID.
2676 The actual buffer position returned is the position of the first
2677 character of the text, after the footnote's identifier. If no
2678 footnote text is found, NIL is returned."
2679 (save-excursion
2680 (goto-char (point-min))
2681 (when (re-search-forward (concat "^\\[" id "\\]:") nil t)
2682 (skip-chars-forward "[ \t]")
2683 (point))))
2684
2685 (defun markdown-footnote-marker-positions ()
2686 "Return the position and ID of the footnote marker point is on.
2687 The return value is a list (ID START END). If point is not on a
2688 footnote, NIL is returned."
2689 ;; first make sure we're at a footnote marker
2690 (if (or (looking-back (concat "\\[\\^" markdown-footnote-chars "*\\]?") (line-beginning-position))
2691 (looking-at (concat "\\[?\\^" markdown-footnote-chars "*?\\]")))
2692 (save-excursion
2693 ;; move point between [ and ^:
2694 (if (looking-at "\\[")
2695 (forward-char 1)
2696 (skip-chars-backward "^["))
2697 (looking-at (concat "\\(\\^" markdown-footnote-chars "*?\\)\\]"))
2698 (list (match-string 1) (1- (match-beginning 1)) (1+ (match-end 1))))))
2699
2700 (defun markdown-footnote-text-positions ()
2701 "Return the start and end positions of the footnote text point is in.
2702 The exact return value is a list of three elements: (ID START END).
2703 The start position is the position of the opening bracket
2704 of the footnote id. The end position is directly after the
2705 newline that ends the footnote. If point is not in a footnote,
2706 NIL is returned instead."
2707 (save-excursion
2708 (let ((fn (progn
2709 (backward-paragraph)
2710 ;; if we're in a multiparagraph footnote, we need to back up further
2711 (while (>= (markdown-next-line-indent) 4)
2712 (backward-paragraph))
2713 (forward-line)
2714 (if (looking-at (concat "^\\[\\(\\^" markdown-footnote-chars "*?\\)\\]:"))
2715 (list (match-string 1) (point))))))
2716 (when fn
2717 (while (progn
2718 (forward-paragraph)
2719 (>= (markdown-next-line-indent) 4)))
2720 (append fn (list (point)))))))
2721
2722 \f
2723 ;;; Element Removal ===========================================================
2724
2725 (defun markdown-kill-thing-at-point ()
2726 "Kill thing at point and add important text, without markup, to kill ring.
2727 Possible things to kill include (roughly in order of precedence):
2728 inline code, headers, horizonal rules, links (add link text to
2729 kill ring), images (add alt text to kill ring), angle uri, email
2730 addresses, bold, italics, reference definition (add URI to kill
2731 ring), footnote markers and text (kill both marker and text, add
2732 text to kill ring), and list items."
2733 (interactive "*")
2734 (let (val tmp)
2735 (cond
2736 ;; Inline code
2737 ((markdown-code-at-point-p)
2738 (kill-new (match-string 1))
2739 (delete-region (match-beginning 0) (match-end 0)))
2740 ;; ATX header
2741 ((thing-at-point-looking-at markdown-regex-header-atx)
2742 (kill-new (match-string 2))
2743 (delete-region (match-beginning 0) (match-end 0)))
2744 ;; Setext header
2745 ((thing-at-point-looking-at markdown-regex-header-setext)
2746 (kill-new (match-string 1))
2747 (delete-region (match-beginning 0) (match-end 0)))
2748 ;; Horizonal rule
2749 ((thing-at-point-looking-at markdown-regex-hr)
2750 (kill-new (match-string 0))
2751 (delete-region (match-beginning 0) (match-end 0)))
2752 ;; Inline link or image (add link or alt text to kill ring)
2753 ((thing-at-point-looking-at markdown-regex-link-inline)
2754 (kill-new (match-string 3))
2755 (delete-region (match-beginning 0) (match-end 0)))
2756 ;; Reference link or image (add link or alt text to kill ring)
2757 ((thing-at-point-looking-at markdown-regex-link-reference)
2758 (kill-new (match-string 3))
2759 (delete-region (match-beginning 0) (match-end 0)))
2760 ;; Angle URI (add URL to kill ring)
2761 ((thing-at-point-looking-at markdown-regex-angle-uri)
2762 (kill-new (match-string 2))
2763 (delete-region (match-beginning 0) (match-end 0)))
2764 ;; Email address in angle brackets (add email address to kill ring)
2765 ((thing-at-point-looking-at markdown-regex-email)
2766 (kill-new (match-string 1))
2767 (delete-region (match-beginning 0) (match-end 0)))
2768 ;; Wiki link (add alias text to kill ring)
2769 ((thing-at-point-looking-at markdown-regex-wiki-link)
2770 (kill-new (markdown-wiki-link-alias))
2771 (delete-region (match-beginning 1) (match-end 1)))
2772 ;; Bold
2773 ((thing-at-point-looking-at markdown-regex-bold)
2774 (kill-new (match-string 4))
2775 (delete-region (match-beginning 2) (match-end 2)))
2776 ;; Italics
2777 ((thing-at-point-looking-at markdown-regex-italic)
2778 (kill-new (match-string 4))
2779 (delete-region (match-beginning 2) (match-end 2)))
2780 ;; Footnote marker (add footnote text to kill ring)
2781 ((thing-at-point-looking-at markdown-regex-footnote)
2782 (markdown-footnote-kill))
2783 ;; Footnote text (add footnote text to kill ring)
2784 ((setq val (markdown-footnote-text-positions))
2785 (markdown-footnote-kill))
2786 ;; Reference definition (add URL to kill ring)
2787 ((thing-at-point-looking-at markdown-regex-reference-definition)
2788 (kill-new (match-string 2))
2789 (delete-region (match-beginning 0) (match-end 0)))
2790 ;; List item
2791 ((setq val (markdown-cur-list-item-bounds))
2792 (kill-new (delete-and-extract-region (first val) (second val))))
2793 (t
2794 (error "Nothing found at point to kill")))))
2795
2796 \f
2797 ;;; Indentation ====================================================================
2798
2799 (defun markdown-indent-find-next-position (cur-pos positions)
2800 "Return the position after the index of CUR-POS in POSITIONS.
2801 Positions are calculated by `markdown-calc-indents'."
2802 (while (and positions
2803 (not (equal cur-pos (car positions))))
2804 (setq positions (cdr positions)))
2805 (or (cadr positions) 0))
2806
2807 (defun markdown-exdent-find-next-position (cur-pos positions)
2808 "Return the maximal element that precedes CUR-POS from POSITIONS.
2809 Positions are calculated by `markdown-calc-indents'."
2810 (let ((result 0))
2811 (dolist (i positions)
2812 (when (< i cur-pos)
2813 (setq result (max result i))))
2814 result))
2815
2816 (defun markdown-indent-line ()
2817 "Indent the current line using some heuristics.
2818 If the _previous_ command was either `markdown-enter-key' or
2819 `markdown-cycle', then we should cycle to the next
2820 reasonable indentation position. Otherwise, we could have been
2821 called directly by `markdown-enter-key', by an initial call of
2822 `markdown-cycle', or indirectly by `auto-fill-mode'. In
2823 these cases, indent to the default position.
2824 Positions are calculated by `markdown-calc-indents'."
2825 (interactive)
2826 (let ((positions (markdown-calc-indents))
2827 (cur-pos (current-column)))
2828 (if (not (equal this-command 'markdown-cycle))
2829 (indent-line-to (car positions))
2830 (setq positions (sort (delete-dups positions) '<))
2831 (indent-line-to
2832 (markdown-indent-find-next-position cur-pos positions)))))
2833
2834 (defun markdown-calc-indents ()
2835 "Return a list of indentation columns to cycle through.
2836 The first element in the returned list should be considered the
2837 default indentation level. This function does not worry about
2838 duplicate positions, which are handled up by calling functions."
2839 (let (pos prev-line-pos positions)
2840
2841 ;; Indentation of previous line
2842 (setq prev-line-pos (markdown-prev-line-indent))
2843 (setq positions (cons prev-line-pos positions))
2844
2845 ;; Indentation of previous non-list-marker text
2846 (when (setq pos (markdown-prev-non-list-indent))
2847 (setq positions (cons pos positions)))
2848
2849 ;; Indentation required for a pre block in current context
2850 (setq pos (length (markdown-pre-indentation (point))))
2851 (setq positions (cons pos positions))
2852
2853 ;; Indentation of the previous line + tab-width
2854 (if prev-line-pos
2855 (setq positions (cons (+ prev-line-pos tab-width) positions))
2856 (setq positions (cons tab-width positions)))
2857
2858 ;; Indentation of the previous line - tab-width
2859 (if (and prev-line-pos (> prev-line-pos tab-width))
2860 (setq positions (cons (- prev-line-pos tab-width) positions)))
2861
2862 ;; Indentation of all preceeding list markers (when in a list)
2863 (when (setq pos (markdown-calculate-list-levels))
2864 (setq positions (append pos positions)))
2865
2866 ;; First column
2867 (setq positions (cons 0 positions))
2868
2869 ;; Return reversed list
2870 (reverse positions)))
2871
2872 (defun markdown-enter-key ()
2873 "Handle RET according to to the value of `markdown-indent-on-enter'."
2874 (interactive)
2875 (if markdown-indent-on-enter
2876 (newline-and-indent)
2877 (newline)))
2878
2879 (defun markdown-exdent-or-delete (arg)
2880 "Handle BACKSPACE by cycling through indentation points.
2881 When BACKSPACE is pressed, if there is only whitespace
2882 before the current point, then exdent the line one level.
2883 Otherwise, do normal delete by repeating
2884 `backward-delete-char-untabify' ARG times."
2885 (interactive "*p")
2886 (let ((cur-pos (current-column))
2887 (start-of-indention (save-excursion
2888 (back-to-indentation)
2889 (current-column)))
2890 (positions (markdown-calc-indents)))
2891 (if (and (> cur-pos 0) (= cur-pos start-of-indention))
2892 (indent-line-to (markdown-exdent-find-next-position cur-pos positions))
2893 (backward-delete-char-untabify arg))))
2894
2895 (defun markdown-find-leftmost-column (beg end)
2896 "Find the leftmost column in the region from BEG to END."
2897 (let ((mincol 1000))
2898 (save-excursion
2899 (goto-char beg)
2900 (while (< (point) end)
2901 (back-to-indentation)
2902 (unless (looking-at "[ \t]*$")
2903 (setq mincol (min mincol (current-column))))
2904 (forward-line 1)
2905 ))
2906 mincol))
2907
2908 (defun markdown-indent-region (beg end arg)
2909 "Indent the region from BEG to END using some heuristics.
2910 When ARG is non-nil, exdent the region instead.
2911 See `markdown-indent-line' and `markdown-indent-line'."
2912 (interactive "*r\nP")
2913 (let* ((positions (sort (delete-dups (markdown-calc-indents)) '<))
2914 (leftmostcol (markdown-find-leftmost-column beg end))
2915 (next-pos (if arg
2916 (markdown-exdent-find-next-position leftmostcol positions)
2917 (markdown-indent-find-next-position leftmostcol positions))))
2918 (indent-rigidly beg end (- next-pos leftmostcol))
2919 (setq deactivate-mark nil)))
2920
2921 (defun markdown-exdent-region (beg end)
2922 "Call `markdown-indent-region' on region from BEG to END with prefix."
2923 (interactive "*r")
2924 (markdown-indent-region (region-beginning) (region-end) t))
2925
2926 \f
2927 ;;; Markup Completion =========================================================
2928
2929 (defconst markdown-complete-alist
2930 '((markdown-regex-header-atx . markdown-complete-atx)
2931 (markdown-regex-header-setext . markdown-complete-setext)
2932 (markdown-regex-hr . markdown-complete-hr))
2933 "Association list of form (regexp . function) for markup completion.")
2934
2935 (defun markdown-incomplete-atx-p ()
2936 "Return t if ATX header markup is incomplete and nil otherwise.
2937 Assumes match data is available for `markdown-regex-header-atx'.
2938 Checks that the number of trailing hash marks equals the number of leading
2939 hash marks, that there is only a single space before and after the text,
2940 and that there is no extraneous whitespace in the text."
2941 (save-match-data
2942 (or
2943 ;; Number of starting and ending hash marks differs
2944 (not (= (length (match-string 1)) (length (match-string 3))))
2945 ;; When the header text is not empty...
2946 (and (> (length (match-string 2)) 0)
2947 ;; ...if there are extra leading, trailing, or interior spaces
2948 (or (not (= (match-beginning 2) (1+ (match-end 1))))
2949 (not (= (match-beginning 3) (1+ (match-end 2))))
2950 (string-match "[ \t\n]\\{2\\}" (match-string 2))))
2951 ;; When the header text is empty...
2952 (and (= (length (match-string 2)) 0)
2953 ;; ...if there are too many or too few spaces
2954 (not (= (match-beginning 3) (+ (match-end 1) 2)))))))
2955
2956 (defun markdown-complete-atx ()
2957 "Complete and normalize ATX headers.
2958 Add or remove hash marks to the end of the header to match the
2959 beginning. Ensure that there is only a single space between hash
2960 marks and header text. Removes extraneous whitespace from header text.
2961 Assumes match data is available for `markdown-regex-header-atx'.
2962 Return nil if markup was complete and non-nil if markup was completed."
2963 (when (markdown-incomplete-atx-p)
2964 (let* ((new-marker (make-marker))
2965 (new-marker (set-marker new-marker (match-end 2))))
2966 ;; Hash marks and spacing at end
2967 (goto-char (match-end 2))
2968 (delete-region (match-end 2) (match-end 3))
2969 (insert " " (match-string 1))
2970 ;; Remove extraneous whitespace from title
2971 (replace-match (markdown-compress-whitespace-string (match-string 2))
2972 t t nil 2)
2973 ;; Spacing at beginning
2974 (goto-char (match-end 1))
2975 (delete-region (match-end 1) (match-beginning 2))
2976 (insert " ")
2977 ;; Leave point at end of text
2978 (goto-char new-marker))))
2979
2980 (defun markdown-incomplete-setext-p ()
2981 "Return t if setext header markup is incomplete and nil otherwise.
2982 Assumes match data is available for `markdown-regex-header-setext'.
2983 Checks that length of underline matches text and that there is no
2984 extraneous whitespace in the text."
2985 (save-match-data
2986 (or (not (= (length (match-string 1)) (length (match-string 2))))
2987 (string-match "[ \t\n]\\{2\\}" (match-string 1)))))
2988
2989 (defun markdown-complete-setext ()
2990 "Complete and normalize setext headers.
2991 Add or remove underline characters to match length of header
2992 text. Removes extraneous whitespace from header text. Assumes
2993 match data is available for `markdown-regex-header-setext'.
2994 Return nil if markup was complete and non-nil if markup was completed."
2995 (when (markdown-incomplete-setext-p)
2996 (let* ((text (markdown-compress-whitespace-string (match-string 1)))
2997 (char (char-after (match-beginning 2)))
2998 (level (if (char-equal char ?-) 2 1)))
2999 (goto-char (match-beginning 0))
3000 (delete-region (match-beginning 0) (match-end 0))
3001 (markdown-insert-header level text t)
3002 t)))
3003
3004 (defun markdown-incomplete-hr-p ()
3005 "Return non-nil if hr is not in `markdown-hr-strings' and nil otherwise.
3006 Assumes match data is available for `markdown-regex-hr'."
3007 (not (member (match-string 0) markdown-hr-strings)))
3008
3009 (defun markdown-complete-hr ()
3010 "Complete horizontal rules.
3011 If horizontal rule string is a member of `markdown-hr-strings',
3012 do nothing. Otherwise, replace with the car of
3013 `markdown-hr-strings'.
3014 Assumes match data is available for `markdown-regex-hr'.
3015 Return nil if markup was complete and non-nil if markup was completed."
3016 (when (markdown-incomplete-hr-p)
3017 (replace-match (car markdown-hr-strings))
3018 t))
3019
3020 (defun markdown-complete ()
3021 "Complete markup of object near point or in region when active.
3022 Handle all objects in `markdown-complete-alist', in order.
3023 See `markdown-complete-at-point' and `markdown-complete-region'."
3024 (interactive "*")
3025 (if (markdown-use-region-p)
3026 (markdown-complete-region (region-beginning) (region-end))
3027 (markdown-complete-at-point)))
3028
3029 (defun markdown-complete-at-point ()
3030 "Complete markup of object near point.
3031 Handle all elements of `markdown-complete-alist' in order."
3032 (interactive "*")
3033 (let ((list markdown-complete-alist) found changed)
3034 (while list
3035 (let ((regexp (eval (caar list)))
3036 (function (cdar list)))
3037 (setq list (cdr list))
3038 (when (thing-at-point-looking-at regexp)
3039 (setq found t)
3040 (setq changed (funcall function))
3041 (setq list nil))))
3042 (if found
3043 (or changed (error "Markup at point is complete"))
3044 (error "Nothing to complete at point"))))
3045
3046 (defun markdown-complete-region (beg end)
3047 "Complete markup of objects in region from BEG to END.
3048 Handle all objects in `markdown-complete-alist', in order. Each
3049 match is checked to ensure that a previous regexp does not also
3050 match."
3051 (interactive "*r")
3052 (let ((end-marker (set-marker (make-marker) end))
3053 previous)
3054 (dolist (element markdown-complete-alist)
3055 (let ((regexp (eval (car element)))
3056 (function (cdr element)))
3057 (goto-char beg)
3058 (while (re-search-forward regexp end-marker 'limit)
3059 (when (match-string 0)
3060 ;; Make sure this is not a match for any of the preceding regexps.
3061 ;; This prevents mistaking an HR for a Setext subheading.
3062 (let (match)
3063 (save-match-data
3064 (dolist (prev-regexp previous)
3065 (or match (setq match (looking-back prev-regexp)))))
3066 (unless match
3067 (save-excursion (funcall function))))))
3068 (add-to-list 'previous regexp)))))
3069
3070 (defun markdown-complete-buffer ()
3071 "Complete markup for all objects in the current buffer."
3072 (interactive "*")
3073 (markdown-complete-region (point-min) (point-max)))
3074
3075 \f
3076 ;;; Markup Cycling ============================================================
3077
3078 (defun markdown-cycle-atx (arg &optional remove)
3079 "Cycle ATX header markup.
3080 Promote header (decrease level) when ARG is 1 and demote
3081 header (increase level) if arg is -1. When REMOVE is non-nil,
3082 remove the header when the level reaches zero and stop cycling
3083 when it reaches six. Otherwise, perform a proper cycling through
3084 levels one through six. Assumes match data is available for
3085 `markdown-regex-header-atx'."
3086 (let* ((old-level (length (match-string 1)))
3087 (new-level (+ old-level arg))
3088 (text (match-string 2)))
3089 (when (not remove)
3090 (setq new-level (% new-level 6))
3091 (setq new-level (cond ((= new-level 0) 6)
3092 ((< new-level 0) (+ new-level 6))
3093 (t new-level))))
3094 (cond
3095 ((= new-level 0)
3096 (markdown-unwrap-thing-at-point nil 0 2))
3097 ((<= new-level 6)
3098 (goto-char (match-beginning 0))
3099 (delete-region (match-beginning 0) (match-end 0))
3100 (markdown-insert-header new-level text nil)))))
3101
3102 (defun markdown-cycle-setext (arg &optional remove)
3103 "Cycle setext header markup.
3104 Promote header (increase level) when ARG is 1 and demote
3105 header (decrease level or remove) if arg is -1. When demoting a
3106 level-two setext header, replace with a level-three atx header.
3107 When REMOVE is non-nil, remove the header when the level reaches
3108 zero. Otherwise, cycle back to a level six atx header. Assumes
3109 match data is available for `markdown-regex-header-setext'."
3110 (let* ((char (char-after (match-beginning 2)))
3111 (old-level (if (char-equal char ?=) 1 2))
3112 (new-level (+ old-level arg))
3113 (text (match-string 1)))
3114 (when (and (not remove) (= new-level 0))
3115 (setq new-level 6))
3116 (cond
3117 ((= new-level 0)
3118 (markdown-unwrap-thing-at-point nil 0 1))
3119 ((<= new-level 2)
3120 (markdown-insert-header new-level nil t))
3121 ((<= new-level 6)
3122 (markdown-insert-header new-level nil nil)))))
3123
3124 (defun markdown-cycle-hr (arg &optional remove)
3125 "Cycle string used for horizontal rule from `markdown-hr-strings'.
3126 When ARG is 1, cycle forward (demote), and when ARG is -1, cycle
3127 backwards (promote). When REMOVE is non-nil, remove the hr instead
3128 of cycling when the end of the list is reached.
3129 Assumes match data is available for `markdown-regex-hr'."
3130 (let* ((strings (if (= arg -1)
3131 (reverse markdown-hr-strings)
3132 markdown-hr-strings))
3133 (tail (member (match-string 0) strings))
3134 (new (or (cadr tail)
3135 (if remove
3136 (if (= arg 1)
3137 ""
3138 (car tail))
3139 (car strings)))))
3140 (replace-match new)))
3141
3142 (defun markdown-cycle-bold ()
3143 "Cycle bold markup between underscores and asterisks.
3144 Assumes match data is available for `markdown-regex-bold'."
3145 (save-excursion
3146 (let* ((old-delim (match-string 3))
3147 (new-delim (if (string-equal old-delim "**") "__" "**")))
3148 (replace-match new-delim t t nil 3)
3149 (replace-match new-delim t t nil 5))))
3150
3151 (defun markdown-cycle-italic ()
3152 "Cycle italic markup between underscores and asterisks.
3153 Assumes match data is available for `markdown-regex-italic'."
3154 (save-excursion
3155 (let* ((old-delim (match-string 3))
3156 (new-delim (if (string-equal old-delim "*") "_" "*")))
3157 (replace-match new-delim t t nil 3)
3158 (replace-match new-delim t t nil 5))))
3159
3160 \f
3161 ;;; Keymap ====================================================================
3162
3163 (defvar markdown-mode-map
3164 (let ((map (make-keymap)))
3165 ;; Element insertion
3166 (define-key map "\C-c\C-al" 'markdown-insert-link)
3167 (define-key map "\C-c\C-aL" 'markdown-insert-reference-link-dwim)
3168 (define-key map "\C-c\C-au" 'markdown-insert-uri)
3169 (define-key map "\C-c\C-af" 'markdown-insert-footnote)
3170 (define-key map "\C-c\C-aw" 'markdown-insert-wiki-link)
3171 (define-key map "\C-c\C-ii" 'markdown-insert-image)
3172 (define-key map "\C-c\C-iI" 'markdown-insert-reference-image)
3173 (define-key map "\C-c\C-th" 'markdown-insert-header-dwim)
3174 (define-key map "\C-c\C-tH" 'markdown-insert-header-setext-dwim)
3175 (define-key map "\C-c\C-t1" 'markdown-insert-header-atx-1)
3176 (define-key map "\C-c\C-t2" 'markdown-insert-header-atx-2)
3177 (define-key map "\C-c\C-t3" 'markdown-insert-header-atx-3)
3178 (define-key map "\C-c\C-t4" 'markdown-insert-header-atx-4)
3179 (define-key map "\C-c\C-t5" 'markdown-insert-header-atx-5)
3180 (define-key map "\C-c\C-t6" 'markdown-insert-header-atx-6)
3181 (define-key map "\C-c\C-t!" 'markdown-insert-header-setext-1)
3182 (define-key map "\C-c\C-t@" 'markdown-insert-header-setext-2)
3183 (define-key map "\C-c\C-ss" 'markdown-insert-bold)
3184 (define-key map "\C-c\C-se" 'markdown-insert-italic)
3185 (define-key map "\C-c\C-sc" 'markdown-insert-code)
3186 (define-key map "\C-c\C-sb" 'markdown-insert-blockquote)
3187 (define-key map "\C-c\C-s\C-b" 'markdown-blockquote-region)
3188 (define-key map "\C-c\C-sp" 'markdown-insert-pre)
3189 (define-key map "\C-c\C-s\C-p" 'markdown-pre-region)
3190 (define-key map "\C-c-" 'markdown-insert-hr)
3191 ;; Element insertion (deprecated)
3192 (define-key map "\C-c\C-ar" 'markdown-insert-reference-link-dwim)
3193 (define-key map "\C-c\C-tt" 'markdown-insert-header-setext-1)
3194 (define-key map "\C-c\C-ts" 'markdown-insert-header-setext-2)
3195 ;; Element removal
3196 (define-key map (kbd "C-c C-k") 'markdown-kill-thing-at-point)
3197 ;; Promotion, Demotion, Completion, and Cycling
3198 (define-key map (kbd "C-c C--") 'markdown-promote)
3199 (define-key map (kbd "C-c C-=") 'markdown-demote)
3200 (define-key map (kbd "C-c C-]") 'markdown-complete)
3201 ;; Following and Jumping
3202 (define-key map (kbd "C-c C-o") 'markdown-follow-thing-at-point)
3203 (define-key map (kbd "C-c C-j") 'markdown-jump)
3204 ;; Indentation
3205 (define-key map (kbd "C-m") 'markdown-enter-key)
3206 (define-key map (kbd "<backspace>") 'markdown-exdent-or-delete)
3207 (define-key map (kbd "C-c >") 'markdown-indent-region)
3208 (define-key map (kbd "C-c <") 'markdown-exdent-region)
3209 ;; Visibility cycling
3210 (define-key map (kbd "<tab>") 'markdown-cycle)
3211 (define-key map (kbd "<S-iso-lefttab>") 'markdown-shifttab)
3212 (define-key map (kbd "<S-tab>") 'markdown-shifttab)
3213 (define-key map (kbd "<backtab>") 'markdown-shifttab)
3214 ;; Header navigation
3215 (define-key map (kbd "C-c C-n") 'outline-next-visible-heading)
3216 (define-key map (kbd "C-c C-p") 'outline-previous-visible-heading)
3217 (define-key map (kbd "C-c C-f") 'outline-forward-same-level)
3218 (define-key map (kbd "C-c C-b") 'outline-backward-same-level)
3219 (define-key map (kbd "C-c C-u") 'outline-up-heading)
3220 ;; Buffer-wide commands
3221 (define-key map (kbd "C-c C-c m") 'markdown-other-window)
3222 (define-key map (kbd "C-c C-c p") 'markdown-preview)
3223 (define-key map (kbd "C-c C-c e") 'markdown-export)
3224 (define-key map (kbd "C-c C-c v") 'markdown-export-and-preview)
3225 (define-key map (kbd "C-c C-c o") 'markdown-open)
3226 (define-key map (kbd "C-c C-c w") 'markdown-kill-ring-save)
3227 (define-key map (kbd "C-c C-c c") 'markdown-check-refs)
3228 (define-key map (kbd "C-c C-c n") 'markdown-cleanup-list-numbers)
3229 (define-key map (kbd "C-c C-c ]") 'markdown-complete-buffer)
3230 ;; List editing
3231 (define-key map (kbd "M-<up>") 'markdown-move-up)
3232 (define-key map (kbd "M-<down>") 'markdown-move-down)
3233 (define-key map (kbd "M-<left>") 'markdown-promote)
3234 (define-key map (kbd "M-<right>") 'markdown-demote)
3235 (define-key map (kbd "M-<return>") 'markdown-insert-list-item)
3236 ;; Movement
3237 (define-key map (kbd "M-{") 'markdown-backward-paragraph)
3238 (define-key map (kbd "M-}") 'markdown-forward-paragraph)
3239 (define-key map (kbd "M-n") 'markdown-next-link)
3240 (define-key map (kbd "M-p") 'markdown-previous-link)
3241 ;; Alternative keys (in case of problems with the arrow keys)
3242 (define-key map (kbd "C-c C-x u") 'markdown-move-up)
3243 (define-key map (kbd "C-c C-x d") 'markdown-move-down)
3244 (define-key map (kbd "C-c C-x l") 'markdown-promote)
3245 (define-key map (kbd "C-c C-x r") 'markdown-demote)
3246 (define-key map (kbd "C-c C-x m") 'markdown-insert-list-item)
3247 (define-key map (kbd "C-c h") 'markdown-hide-other-langs)
3248 (define-key map (kbd "C-c s") 'markdown-unhide-langs)
3249 (define-key map (kbd "C-c b") 'schreib-build)
3250 (define-key map (kbd "C-c c") 'schreib-deploy)
3251
3252 map)
3253 "Keymap for Markdown major mode.")
3254
3255 (defvar gfm-mode-map
3256 (let ((map (make-sparse-keymap)))
3257 (set-keymap-parent map markdown-mode-map)
3258 (define-key map (kbd "C-c C-s P") 'markdown-insert-gfm-code-block)
3259 map)
3260 "Keymap for `gfm-mode'.
3261 See also `markdown-mode-map'.")
3262
3263 \f
3264 ;;; Menu ==================================================================
3265
3266 (easy-menu-define markdown-mode-menu markdown-mode-map
3267 "Menu for Markdown mode"
3268 '("Markdown"
3269 ("Show/Hide"
3270 ["Cycle visibility" markdown-cycle (outline-on-heading-p)]
3271 ["Cycle global visibility" markdown-shifttab])
3272 "---"
3273 ["Compile" markdown-other-window]
3274 ["Preview" markdown-preview]
3275 ["Export" markdown-export]
3276 ["Export & View" markdown-export-and-preview]
3277 ["Open" markdown-open]
3278 ["Kill ring save" markdown-kill-ring-save]
3279 "---"
3280 ("Headings"
3281 ["Automatic" markdown-insert-header-dwim]
3282 ["Automatic (prefer setext)" markdown-insert-header-setext-dwim]
3283 "---"
3284 ["First level setext" markdown-insert-header-setext-1]
3285 ["Second level setext" markdown-insert-header-setext-2]
3286 "---"
3287 ["First level atx" markdown-insert-header-atx-1]
3288 ["Second level atx" markdown-insert-header-atx-2]
3289 ["Third level atx" markdown-insert-header-atx-3]
3290 ["Fourth level atx" markdown-insert-header-atx-4]
3291 ["Fifth level atx" markdown-insert-header-atx-5]
3292 ["Sixth level atx" markdown-insert-header-atx-6])
3293 "---"
3294 ["Bold" markdown-insert-bold]
3295 ["Italic" markdown-insert-italic]
3296 ["Blockquote" markdown-insert-blockquote]
3297 ["Preformatted" markdown-insert-pre]
3298 ["Code" markdown-insert-code]
3299 "---"
3300 ["Insert inline link" markdown-insert-link]
3301 ["Insert reference link" markdown-insert-reference-link-dwim]
3302 ["Insert URL" markdown-insert-uri]
3303 ["Insert inline image" markdown-insert-image]
3304 ["Insert reference image" markdown-insert-reference-image]
3305 ["Insert list item" markdown-insert-list-item]
3306 ["Insert horizontal rule" markdown-insert-hr]
3307 ["Insert footnote" markdown-insert-footnote]
3308 ["Kill element" markdown-kill-thing-at-point]
3309 "---"
3310 ["Jump" markdown-jump]
3311 ["Follow link" markdown-follow-thing-at-point]
3312 ("Outline"
3313 ["Next visible heading" outline-next-visible-heading]
3314 ["Previous visible heading" outline-previous-visible-heading]
3315 ["Forward same level" outline-forward-same-level]
3316 ["Backward same level" outline-backward-same-level]
3317 ["Up to parent heading" outline-up-heading])
3318 "---"
3319 ("Completion and Cycling"
3320 ["Complete" markdown-complete]
3321 ["Promote" markdown-promote]
3322 ["Demote" markdown-demote])
3323 ("List editing"
3324 ["Indent list item" markdown-demote]
3325 ["Exdent list item" markdown-promote])
3326 ("Region shifting"
3327 ["Indent region" markdown-indent-region]
3328 ["Exdent region" markdown-exdent-region])
3329 "---"
3330 ["Check references" markdown-check-refs]
3331 ["Clean up list numbering" markdown-cleanup-list-numbers]
3332 ["Complete markup" markdown-complete-buffer]
3333 "---"
3334 ["Version" markdown-show-version]
3335 ))
3336
3337 \f
3338 ;;; imenu =====================================================================
3339
3340 (defun markdown-imenu-create-index ()
3341 "Create and return an imenu index alist for the current buffer.
3342 See `imenu-create-index-function' and `imenu--index-alist' for details."
3343 (let* ((root '(nil . nil))
3344 cur-alist
3345 (cur-level 0)
3346 (empty-heading "-")
3347 (self-heading ".")
3348 hashes pos level heading)
3349 (save-excursion
3350 (goto-char (point-min))
3351 (while (re-search-forward markdown-regex-header (point-max) t)
3352 (cond
3353 ((setq heading (match-string-no-properties 1))
3354 (setq pos (match-beginning 1)
3355 level 1))
3356 ((setq heading (match-string-no-properties 3))
3357 (setq pos (match-beginning 3)
3358 level 2))
3359 ((setq hashes (match-string-no-properties 5))
3360 (setq heading (match-string-no-properties 6)
3361 pos (match-beginning 5)
3362 level (length hashes))))
3363 (let ((alist (list (cons heading pos))))
3364 (cond
3365 ((= cur-level level) ; new sibling
3366 (setcdr cur-alist alist)
3367 (setq cur-alist alist))
3368 ((< cur-level level) ; first child
3369 (dotimes (i (- level cur-level 1))
3370 (setq alist (list (cons empty-heading alist))))
3371 (if cur-alist
3372 (let* ((parent (car cur-alist))
3373 (self-pos (cdr parent)))
3374 (setcdr parent (cons (cons self-heading self-pos) alist)))
3375 (setcdr root alist)) ; primogenitor
3376 (setq cur-alist alist)
3377 (setq cur-level level))
3378 (t ; new sibling of an ancestor
3379 (let ((sibling-alist (last (cdr root))))
3380 (dotimes (i (1- level))
3381 (setq sibling-alist (last (cdar sibling-alist))))
3382 (setcdr sibling-alist alist)
3383 (setq cur-alist alist))
3384 (setq cur-level level)))))
3385 (cdr root))))
3386
3387 \f
3388 ;;; References ================================================================
3389
3390 (defun markdown-insert-reference-definition (ref &optional buffer)
3391 "Add blank REF definition to the end of BUFFER.
3392 REF is a Markdown reference in square brackets, like \"[lisp-history]\"."
3393 (or buffer (setq buffer (current-buffer)))
3394 (with-current-buffer buffer
3395 (goto-char (point-max))
3396 (indent-new-comment-line)
3397 (insert (concat ref ": "))))
3398
3399 (defun markdown-reference-goto-definition ()
3400 "Jump to the definition of the reference at point or create it."
3401 (interactive)
3402 (when (thing-at-point-looking-at markdown-regex-link-reference)
3403 (let* ((text (match-string-no-properties 2))
3404 (reference (match-string-no-properties 4))
3405 (target (downcase (if (string= reference "[]") text reference)))
3406 (loc (cadr (markdown-reference-definition target))))
3407 (if loc
3408 (goto-char loc)
3409 (markdown-insert-reference-definition target (current-buffer))))))
3410
3411 (defun markdown-reference-find-links (reference)
3412 "Return a list of all links for REFERENCE.
3413 REFERENCE should include the surrounding square brackets like [this].
3414 Elements of the list have the form (text start line), where
3415 text is the link text, start is the location at the beginning of
3416 the link, and line is the line number on which the link appears."
3417 (let* ((ref-quote (regexp-quote (substring reference 1 -1)))
3418 (regexp (format "!?\\(?:\\[\\(%s\\)\\][ ]?\\[\\]\\|\\[\\([^]]+?\\)\\][ ]?\\[%s\\]\\)"
3419 ref-quote ref-quote))
3420 links)
3421 (save-excursion
3422 (goto-char (point-min))
3423 (while (re-search-forward regexp nil t)
3424 (let* ((text (or (match-string-no-properties 1)
3425 (match-string-no-properties 2)))
3426 (start (match-beginning 0))
3427 (line (markdown-line-number-at-pos)))
3428 (add-to-list 'links (list text start line)))))
3429 links))
3430
3431 (defun markdown-get-undefined-refs ()
3432 "Return a list of undefined Markdown references.
3433 Result is an alist of pairs (reference . occurrences), where
3434 occurrences is itself another alist of pairs (label . line-number).
3435 For example, an alist corresponding to [Nice editor][Emacs] at line 12,
3436 \[GNU Emacs][Emacs] at line 45 and [manual][elisp] at line 127 is
3437 \((\"[emacs]\" (\"[Nice editor]\" . 12) (\"[GNU Emacs]\" . 45)) (\"[elisp]\" (\"[manual]\" . 127)))."
3438 (let ((missing))
3439 (save-excursion
3440 (goto-char (point-min))
3441 (while
3442 (re-search-forward markdown-regex-link-reference nil t)
3443 (let* ((text (match-string-no-properties 2))
3444 (reference (match-string-no-properties 4))
3445 (target (downcase (if (string= reference "[]") text reference))))
3446 (unless (markdown-reference-definition target)
3447 (let ((entry (assoc target missing)))
3448 (if (not entry)
3449 (add-to-list 'missing (cons target
3450 (list (cons text (markdown-line-number-at-pos)))) t)
3451 (setcdr entry
3452 (append (cdr entry) (list (cons text (markdown-line-number-at-pos))))))))))
3453 missing)))
3454
3455 (defconst markdown-reference-check-buffer
3456 "*Undefined references for %buffer%*"
3457 "Pattern for name of buffer for listing undefined references.
3458 The string %buffer% will be replaced by the corresponding
3459 `markdown-mode' buffer name.")
3460
3461 (defun markdown-reference-check-buffer (&optional buffer-name)
3462 "Name and return buffer for reference checking.
3463 BUFFER-NAME is the name of the main buffer being visited."
3464 (or buffer-name (setq buffer-name (buffer-name)))
3465 (let ((refbuf (get-buffer-create (markdown-replace-regexp-in-string
3466 "%buffer%" buffer-name
3467 markdown-reference-check-buffer))))
3468 (with-current-buffer refbuf
3469 (when view-mode
3470 (View-exit-and-edit))
3471 (use-local-map button-buffer-map)
3472 (erase-buffer))
3473 refbuf))
3474
3475 (defconst markdown-reference-links-buffer
3476 "*Reference links for %buffer%*"
3477 "Pattern for name of buffer for listing references.
3478 The string %buffer% will be replaced by the corresponding buffer name.")
3479
3480 (defun markdown-reference-links-buffer (&optional buffer-name)
3481 "Name, setup, and return a buffer for listing links.
3482 BUFFER-NAME is the name of the main buffer being visited."
3483 (or buffer-name (setq buffer-name (buffer-name)))
3484 (let ((linkbuf (get-buffer-create (markdown-replace-regexp-in-string
3485 "%buffer%" buffer-name
3486 markdown-reference-links-buffer))))
3487 (with-current-buffer linkbuf
3488 (when view-mode
3489 (View-exit-and-edit))
3490 (use-local-map button-buffer-map)
3491 (erase-buffer))
3492 linkbuf))
3493
3494 (when (markdown-use-buttons-p)
3495 ;; Add an empty Markdown reference definition to the end of buffer
3496 ;; specified in the 'target-buffer property. The reference name is
3497 ;; the button's label.
3498 (define-button-type 'markdown-undefined-reference-button
3499 'help-echo "mouse-1, RET: create definition for undefined reference"
3500 'follow-link t
3501 'face 'bold
3502 'action (lambda (b)
3503 (let ((buffer (button-get b 'target-buffer)))
3504 (markdown-insert-reference-definition (button-label b) buffer)
3505 (switch-to-buffer-other-window buffer)
3506 (goto-char (point-max))
3507 (markdown-check-refs t))))
3508
3509 ;; Jump to line in buffer specified by 'target-buffer property.
3510 ;; Line number is button's 'line property.
3511 (define-button-type 'markdown-goto-line-button
3512 'help-echo "mouse-1, RET: go to line"
3513 'follow-link t
3514 'face 'italic
3515 'action (lambda (b)
3516 (message (button-get b 'buffer))
3517 (switch-to-buffer-other-window (button-get b 'target-buffer))
3518 ;; use call-interactively to silence compiler
3519 (let ((current-prefix-arg (button-get b 'target-line)))
3520 (call-interactively 'goto-line))))
3521
3522 ;; Jumps to a particular link at location given by 'target-char
3523 ;; property in buffer given by 'target-buffer property.
3524 (define-button-type 'markdown-link-button
3525 'help-echo "mouse-1, RET: jump to location of link"
3526 'follow-link t
3527 'face 'bold
3528 'action (lambda (b)
3529 (let ((target (button-get b 'target-buffer))
3530 (loc (button-get b 'target-char)))
3531 (kill-buffer-and-window)
3532 (switch-to-buffer target)
3533 (goto-char loc)))))
3534
3535 (defun markdown-insert-undefined-reference-button (reference oldbuf)
3536 "Insert a button for creating REFERENCE in buffer OLDBUF.
3537 REFERENCE should be a list of the form (reference . occurrences),
3538 as by `markdown-get-undefined-refs'."
3539 (let ((label (car reference)))
3540 (if (markdown-use-buttons-p)
3541 ;; Create a reference button in Emacs 22
3542 (insert-button label
3543 :type 'markdown-undefined-reference-button
3544 'target-buffer oldbuf)
3545 ;; Insert reference as text in Emacs < 22
3546 (insert label))
3547 (insert " (")
3548 (dolist (occurrence (cdr reference))
3549 (let ((line (cdr occurrence)))
3550 (if (markdown-use-buttons-p)
3551 ;; Create a line number button in Emacs 22
3552 (insert-button (number-to-string line)
3553 :type 'markdown-goto-line-button
3554 'target-buffer oldbuf
3555 'target-line line)
3556 ;; Insert line number as text in Emacs < 22
3557 (insert (number-to-string line)))
3558 (insert " ")))
3559 (delete-char -1)
3560 (insert ")")
3561 (newline)))
3562
3563 (defun markdown-insert-link-button (link oldbuf)
3564 "Insert a button for jumping to LINK in buffer OLDBUF.
3565 LINK should be a list of the form (text char line) containing
3566 the link text, location, and line number."
3567 (let ((label (first link))
3568 (char (second link))
3569 (line (third link)))
3570 (if (markdown-use-buttons-p)
3571 ;; Create a reference button in Emacs 22
3572 (insert-button label
3573 :type 'markdown-link-button
3574 'target-buffer oldbuf
3575 'target-char char)
3576 ;; Insert reference as text in Emacs < 22
3577 (insert label))
3578 (insert (format " (line %d)\n" line))))
3579
3580 (defun markdown-reference-goto-link (&optional reference)
3581 "Jump to the location of the first use of REFERENCE."
3582 (interactive)
3583 (unless reference
3584 (if (thing-at-point-looking-at markdown-regex-reference-definition)
3585 (setq reference (match-string-no-properties 1))
3586 (error "No reference definition at point")))
3587 (let ((links (markdown-reference-find-links reference)))
3588 (cond ((= (length links) 1)
3589 (goto-char (cadr (car links))))
3590 ((> (length links) 1)
3591 (let ((oldbuf (current-buffer))
3592 (linkbuf (markdown-reference-links-buffer)))
3593 (with-current-buffer linkbuf
3594 (insert "Links using reference " reference ":\n\n")
3595 (dolist (link (reverse links))
3596 (markdown-insert-link-button link oldbuf)))
3597 (view-buffer-other-window linkbuf)
3598 (goto-char (point-min))
3599 (forward-line 2)))
3600 (t
3601 (error "No links for reference %s" reference)))))
3602
3603 (defun markdown-check-refs (&optional silent)
3604 "Show all undefined Markdown references in current `markdown-mode' buffer.
3605 If SILENT is non-nil, do not message anything when no undefined
3606 references found.
3607 Links which have empty reference definitions are considered to be
3608 defined."
3609 (interactive "P")
3610 (when (not (eq major-mode 'markdown-mode))
3611 (error "Not available in current mode"))
3612 (let ((oldbuf (current-buffer))
3613 (refs (markdown-get-undefined-refs))
3614 (refbuf (markdown-reference-check-buffer)))
3615 (if (null refs)
3616 (progn
3617 (when (not silent)
3618 (message "No undefined references found"))
3619 (kill-buffer refbuf))
3620 (with-current-buffer refbuf
3621 (insert "The following references are undefined:\n\n")
3622 (dolist (ref refs)
3623 (markdown-insert-undefined-reference-button ref oldbuf))
3624 (view-buffer-other-window refbuf)
3625 (goto-char (point-min))
3626 (forward-line 2)))))
3627
3628 \f
3629 ;;; Lists =====================================================================
3630
3631 (defun markdown-insert-list-item (&optional arg)
3632 "Insert a new list item.
3633 If the point is inside unordered list, insert a bullet mark. If
3634 the point is inside ordered list, insert the next number followed
3635 by a period. Use the previous list item to determine the amount
3636 of whitespace to place before and after list markers.
3637
3638 With a \\[universal-argument] prefix (i.e., when ARG is (4)),
3639 decrease the indentation by one level.
3640
3641 With two \\[universal-argument] prefixes (i.e., when ARG is (16)),
3642 increase the indentation by one level."
3643 (interactive "p")
3644 (let (bounds item-indent marker indent new-indent new-loc)
3645 (save-match-data
3646 ;; Look for a list item on current or previous non-blank line
3647 (save-excursion
3648 (while (and (not (setq bounds (markdown-cur-list-item-bounds)))
3649 (not (bobp))
3650 (markdown-cur-line-blank-p))
3651 (forward-line -1)))
3652 (when bounds
3653 (cond ((save-excursion
3654 (skip-chars-backward " \t")
3655 (looking-at markdown-regex-list))
3656 (beginning-of-line)
3657 (insert "\n")
3658 (forward-line -1))
3659 ((not (markdown-cur-line-blank-p))
3660 (newline)))
3661 (setq new-loc (point)))
3662 ;; Look ahead for a list item on next non-blank line
3663 (unless bounds
3664 (save-excursion
3665 (while (and (null bounds)
3666 (not (eobp))
3667 (markdown-cur-line-blank-p))
3668 (forward-line)
3669 (setq bounds (markdown-cur-list-item-bounds))))
3670 (when bounds
3671 (setq new-loc (point))
3672 (unless (markdown-cur-line-blank-p)
3673 (newline))))
3674 (if (not bounds)
3675 ;; When not in a list, start a new unordered one
3676 (progn
3677 (unless (markdown-cur-line-blank-p)
3678 (insert "\n"))
3679 (insert "* "))
3680 ;; Compute indentation for a new list item
3681 (setq item-indent (nth 2 bounds))
3682 (setq marker (nth 4 bounds))
3683 (setq indent (cond
3684 ((= arg 4) (max (- item-indent 4) 0))
3685 ((= arg 16) (+ item-indent 4))
3686 (t item-indent)))
3687 (setq new-indent (make-string indent 32))
3688 (goto-char new-loc)
3689 (cond
3690 ;; Ordered list
3691 ((string-match "[0-9]" marker)
3692 (if (= arg 16) ;; starting a new column indented one more level
3693 (insert (concat new-indent "1. "))
3694 ;; travel up to the last item and pick the correct number. If
3695 ;; the argument was nil, "new-indent = item-indent" is the same,
3696 ;; so we don't need special treatment. Neat.
3697 (save-excursion
3698 (while (not (looking-at (concat new-indent "\\([0-9]+\\)\\.")))
3699 (forward-line -1)))
3700 (insert (concat new-indent
3701 (int-to-string (1+ (string-to-number (match-string 1))))
3702 ". "))))
3703 ;; Unordered list
3704 ((string-match "[\\*\\+-]" marker)
3705 (insert new-indent marker)))))))
3706
3707 (defun markdown-move-list-item-up ()
3708 "Move the current list item up in the list when possible."
3709 (interactive)
3710 (let (cur prev old)
3711 (when (setq cur (markdown-cur-list-item-bounds))
3712 (setq old (point))
3713 (goto-char (nth 0 cur))
3714 (if (markdown-prev-list-item (nth 3 cur))
3715 (progn
3716 (setq prev (markdown-cur-list-item-bounds))
3717 (condition-case nil
3718 (progn
3719 (transpose-regions (nth 0 prev) (nth 1 prev)
3720 (nth 0 cur) (nth 1 cur) t)
3721 (goto-char (+ (nth 0 prev) (- old (nth 0 cur)))))
3722 ;; Catch error in case regions overlap.
3723 (error (goto-char old))))
3724 (goto-char old)))))
3725
3726 (defun markdown-move-list-item-down ()
3727 "Move the current list item down in the list when possible."
3728 (interactive)
3729 (let (cur next old)
3730 (when (setq cur (markdown-cur-list-item-bounds))
3731 (setq old (point))
3732 (if (markdown-next-list-item (nth 3 cur))
3733 (progn
3734 (setq next (markdown-cur-list-item-bounds))
3735 (condition-case nil
3736 (progn
3737 (transpose-regions (nth 0 cur) (nth 1 cur)
3738 (nth 0 next) (nth 1 next) nil)
3739 (goto-char (+ old (- (nth 1 next) (nth 1 cur)))))
3740 ;; Catch error in case regions overlap.
3741 (error (goto-char old))))
3742 (goto-char old)))))
3743
3744 (defun markdown-demote-list-item (&optional bounds)
3745 "Indent (or demote) the current list item.
3746 Optionally, BOUNDS of the current list item may be provided if available."
3747 (interactive)
3748 (when (or bounds (setq bounds (markdown-cur-list-item-bounds)))
3749 (save-excursion
3750 (save-match-data
3751 (let* ((end-marker (make-marker))
3752 (end-marker (set-marker end-marker (nth 1 bounds))))
3753 (goto-char (nth 0 bounds))
3754 (while (< (point) end-marker)
3755 (unless (markdown-cur-line-blank-p)
3756 (insert " "))
3757 (forward-line)))))))
3758
3759 (defun markdown-promote-list-item (&optional bounds)
3760 "Unindent (or promote) the current list item.
3761 Optionally, BOUNDS of the current list item may be provided if available."
3762 (interactive)
3763 (when (or bounds (setq bounds (markdown-cur-list-item-bounds)))
3764 (save-excursion
3765 (save-match-data
3766 (let* ((end-marker (make-marker))
3767 (end-marker (set-marker end-marker (nth 1 bounds)))
3768 num regexp)
3769 (goto-char (nth 0 bounds))
3770 (when (looking-at "^[ ]\\{1,4\\}")
3771 (setq num (- (match-end 0) (match-beginning 0)))
3772 (setq regexp (format "^[ ]\\{1,%d\\}" num))
3773 (while (and (< (point) end-marker)
3774 (re-search-forward regexp end-marker t))
3775 (replace-match "" nil nil)
3776 (forward-line))))))))
3777
3778 (defun markdown-cleanup-list-numbers-level (&optional pfx)
3779 "Update the numbering for level PFX (as a string of spaces).
3780
3781 Assume that the previously found match was for a numbered item in
3782 a list."
3783 (let ((cpfx pfx)
3784 (idx 0)
3785 (continue t)
3786 (step t)
3787 (sep nil))
3788 (while (and continue (not (eobp)))
3789 (setq step t)
3790 (cond
3791 ((looking-at "^\\([\s-]*\\)[0-9]+\\. ")
3792 (setq cpfx (match-string-no-properties 1))
3793 (cond
3794 ((string= cpfx pfx)
3795 (replace-match
3796 (concat pfx (number-to-string (setq idx (1+ idx))) ". "))
3797 (setq sep nil))
3798 ;; indented a level
3799 ((string< pfx cpfx)
3800 (setq sep (markdown-cleanup-list-numbers-level cpfx))
3801 (setq step nil))
3802 ;; exit the loop
3803 (t
3804 (setq step nil)
3805 (setq continue nil))))
3806
3807 ((looking-at "^\\([\s-]*\\)[^ \t\n\r].*$")
3808 (setq cpfx (match-string-no-properties 1))
3809 (cond
3810 ;; reset if separated before
3811 ((string= cpfx pfx) (when sep (setq idx 0)))
3812 ((string< cpfx pfx)
3813 (setq step nil)
3814 (setq continue nil))))
3815 (t (setq sep t)))
3816
3817 (when step
3818 (beginning-of-line)
3819 (setq continue (= (forward-line) 0))))
3820 sep))
3821
3822 (defun markdown-cleanup-list-numbers ()
3823 "Update the numbering of ordered lists."
3824 (interactive)
3825 (save-excursion
3826 (goto-char (point-min))
3827 (markdown-cleanup-list-numbers-level "")))
3828
3829 \f
3830 ;;; Outline ===================================================================
3831
3832 (defvar markdown-cycle-global-status 1)
3833 (defvar markdown-cycle-subtree-status nil)
3834
3835 (defun markdown-end-of-subtree (&optional invisible-OK)
3836 "Move to the end of the current subtree.
3837 Only visible heading lines are considered, unless INVISIBLE-OK is
3838 non-nil.
3839 Derived from `org-end-of-subtree'."
3840 (outline-back-to-heading invisible-OK)
3841 (let ((first t)
3842 (level (funcall outline-level)))
3843 (while (and (not (eobp))
3844 (or first (> (funcall outline-level) level)))
3845 (setq first nil)
3846 (outline-next-heading))
3847 (if (memq (preceding-char) '(?\n ?\^M))
3848 (progn
3849 ;; Go to end of line before heading
3850 (forward-char -1)
3851 (if (memq (preceding-char) '(?\n ?\^M))
3852 ;; leave blank line before heading
3853 (forward-char -1)))))
3854 (point))
3855
3856 (defun markdown-cycle (&optional arg)
3857 "Visibility cycling for Markdown mode.
3858 If ARG is t, perform global visibility cycling. If the point is
3859 at an atx-style header, cycle visibility of the corresponding
3860 subtree. Otherwise, insert a tab using `indent-relative'.
3861 Derived from `org-cycle'."
3862 (interactive "P")
3863 (cond
3864 ((eq arg t) ;; Global cycling
3865 (cond
3866 ((and (eq last-command this-command)
3867 (eq markdown-cycle-global-status 2))
3868 ;; Move from overview to contents
3869 (hide-sublevels 1)
3870 (message "CONTENTS")
3871 (setq markdown-cycle-global-status 3))
3872
3873 ((and (eq last-command this-command)
3874 (eq markdown-cycle-global-status 3))
3875 ;; Move from contents to all
3876 (show-all)
3877 (message "SHOW ALL")
3878 (setq markdown-cycle-global-status 1))
3879
3880 (t
3881 ;; Defaults to overview
3882 (hide-body)
3883 (message "OVERVIEW")
3884 (setq markdown-cycle-global-status 2))))
3885
3886 ((save-excursion (beginning-of-line 1) (looking-at outline-regexp))
3887 ;; At a heading: rotate between three different views
3888 (outline-back-to-heading)
3889 (let ((goal-column 0) eoh eol eos)
3890 ;; Determine boundaries
3891 (save-excursion
3892 (outline-back-to-heading)
3893 (save-excursion
3894 (beginning-of-line 2)
3895 (while (and (not (eobp)) ;; this is like `next-line'
3896 (get-char-property (1- (point)) 'invisible))
3897 (beginning-of-line 2)) (setq eol (point)))
3898 (outline-end-of-heading) (setq eoh (point))
3899 (markdown-end-of-subtree t)
3900 (skip-chars-forward " \t\n")
3901 (beginning-of-line 1) ; in case this is an item
3902 (setq eos (1- (point))))
3903 ;; Find out what to do next and set `this-command'
3904 (cond
3905 ((= eos eoh)
3906 ;; Nothing is hidden behind this heading
3907 (message "EMPTY ENTRY")
3908 (setq markdown-cycle-subtree-status nil))
3909 ((>= eol eos)
3910 ;; Entire subtree is hidden in one line: open it
3911 (show-entry)
3912 (show-children)
3913 (message "CHILDREN")
3914 (setq markdown-cycle-subtree-status 'children))
3915 ((and (eq last-command this-command)
3916 (eq markdown-cycle-subtree-status 'children))
3917 ;; We just showed the children, now show everything.
3918 (show-subtree)
3919 (message "SUBTREE")
3920 (setq markdown-cycle-subtree-status 'subtree))
3921 (t
3922 ;; Default action: hide the subtree.
3923 (hide-subtree)
3924 (message "FOLDED")
3925 (setq markdown-cycle-subtree-status 'folded)))))
3926
3927 (t
3928 (indent-for-tab-command))))
3929
3930 (defun markdown-shifttab ()
3931 "Global visibility cycling.
3932 Calls `markdown-cycle' with argument t."
3933 (interactive)
3934 (markdown-cycle t))
3935
3936 (defun markdown-outline-level ()
3937 "Return the depth to which a statement is nested in the outline."
3938 (cond
3939 ((match-end 1) 1)
3940 ((match-end 3) 2)
3941 ((- (match-end 5) (match-beginning 5)))))
3942
3943 \f
3944 ;;; Movement ==================================================================
3945
3946 (defun markdown-beginning-of-defun (&optional arg)
3947 "`beginning-of-defun-function' for Markdown.
3948 Move backward to the beginning of the current or previous section.
3949 When ARG is non-nil, repeat that many times. When ARG is negative,
3950 move forward to the ARG-th following section."
3951 (interactive "P")
3952 (or arg (setq arg 1))
3953 (or (re-search-backward markdown-regex-header nil t arg)
3954 (goto-char (point-min))))
3955
3956 (defun markdown-end-of-defun (&optional arg)
3957 "`end-of-defun-function' for Markdown.
3958 Move forward to the end of the current or following section.
3959 When ARG is non-nil, repeat that many times. When ARG is negative,
3960 move back to the ARG-th preceding section."
3961 (interactive "P")
3962 (or arg (setq arg 1))
3963 (when (looking-at markdown-regex-header)
3964 (goto-char (match-beginning 0))
3965 (forward-char 1))
3966 (if (re-search-forward markdown-regex-header nil t arg)
3967 (goto-char (match-beginning 0))
3968 (goto-char (point-max)))
3969 (skip-syntax-backward "-"))
3970
3971 (defun markdown-beginning-of-block ()
3972 "Move the point to the start of the previous text block."
3973 (interactive)
3974 (if (re-search-backward markdown-regex-block-separator nil t)
3975 (goto-char (or (match-end 2) (match-end 0)))
3976 (goto-char (point-min))))
3977
3978 (defun markdown-end-of-block ()
3979 "Move the point to the start of the next text block."
3980 (interactive)
3981 (beginning-of-line)
3982 (skip-syntax-forward "-")
3983 (when (= (point) (point-min))
3984 (forward-char))
3985 (if (re-search-forward markdown-regex-block-separator nil t)
3986 (goto-char (or (match-end 2) (match-end 0)))
3987 (goto-char (point-max)))
3988 (skip-syntax-backward "-")
3989 (forward-line))
3990
3991 (defun markdown-forward-paragraph (arg)
3992 "Move forward one or more paragraphs or by one block.
3993 When ARG is nil or a numeric prefix, call `forward-paragraph'
3994 with ARG. When called with \\[universal-argument], call
3995 `markdown-end-of-block' instead."
3996 (interactive "P")
3997 (or arg (setq arg 1))
3998 (cond ((integerp arg)
3999 (forward-paragraph arg))
4000 ((equal arg '(4))
4001 (markdown-end-of-block))))
4002
4003 (defun markdown-backward-paragraph (arg)
4004 "Move backward one or more paragraphs or by one block.
4005 When ARG is nil or a numeric prefix, call `backward-paragraph'
4006 with ARG. When called with \\[universal-argument], call
4007 `markdown-beginning-of-block' instead."
4008 (interactive "P")
4009 (or arg (setq arg 1))
4010 (cond ((integerp arg)
4011 (backward-paragraph arg))
4012 ((equal arg '(4))
4013 (markdown-beginning-of-block))))
4014
4015 (defun markdown-end-of-block-element ()
4016 "Move the point to the start of the next block unit.
4017 Stops at blank lines, list items, headers, and horizontal rules."
4018 (interactive)
4019 (forward-line)
4020 (while (and (or (not (markdown-prev-line-blank-p))
4021 (markdown-cur-line-blank-p))
4022 (not (or (looking-at markdown-regex-list)
4023 (looking-at markdown-regex-header)
4024 (looking-at markdown-regex-hr)))
4025 (not (eobp)))
4026 (forward-line)))
4027
4028 (defun markdown-next-link ()
4029 "Jump to next inline, reference, or wiki link.
4030 If successful, return point. Otherwise, return nil.
4031 See `markdown-wiki-link-p' and `markdown-previous-wiki-link'."
4032 (interactive)
4033 (let ((opoint (point)))
4034 (when (or (markdown-link-p) (markdown-wiki-link-p))
4035 ;; At a link already, move past it.
4036 (goto-char (+ (match-end 0) 1)))
4037 ;; Search for the next wiki link and move to the beginning.
4038 (if (re-search-forward markdown-regex-link-generic nil t)
4039 ;; Group 1 will move past non-escape character in wiki link regexp.
4040 ;; Go to beginning of group zero for all other link types.
4041 (goto-char (or (match-beginning 1) (match-beginning 0)))
4042 (goto-char opoint)
4043 nil)))
4044
4045 (defun markdown-previous-link ()
4046 "Jump to previous wiki link.
4047 If successful, return point. Otherwise, return nil.
4048 See `markdown-wiki-link-p' and `markdown-next-wiki-link'."
4049 (interactive)
4050 (if (re-search-backward markdown-regex-link-generic nil t)
4051 (goto-char (or (match-beginning 1) (match-beginning 0)))
4052 nil))
4053
4054 \f
4055 ;;; Generic Structure Editing, Completion, and Cycling Commands ===============
4056
4057 (defun markdown-move-up ()
4058 "Move list item up.
4059 Calls `markdown-move-list-item-up'."
4060 (interactive)
4061 (markdown-move-list-item-up))
4062
4063 (defun markdown-move-down ()
4064 "Move list item down.
4065 Calls `markdown-move-list-item-down'."
4066 (interactive)
4067 (markdown-move-list-item-down))
4068
4069 (defun markdown-promote ()
4070 "Either promote header or list item at point or cycle markup.
4071 See `markdown-cycle-atx', `markdown-cycle-setext', and
4072 `markdown-promote-list-item'."
4073 (interactive)
4074 (let (bounds)
4075 (cond
4076 ;; Promote atx header
4077 ((thing-at-point-looking-at markdown-regex-header-atx)
4078 (markdown-cycle-atx -1))
4079 ;; Promote setext header
4080 ((thing-at-point-looking-at markdown-regex-header-setext)
4081 (markdown-cycle-setext -1))
4082 ;; Promote horizonal rule
4083 ((thing-at-point-looking-at markdown-regex-hr)
4084 (markdown-cycle-hr -1))
4085 ;; Promote list item
4086 ((setq bounds (markdown-cur-list-item-bounds))
4087 (markdown-promote-list-item))
4088 ;; Promote bold
4089 ((thing-at-point-looking-at markdown-regex-bold)
4090 (markdown-cycle-bold))
4091 ;; Promote italic
4092 ((thing-at-point-looking-at markdown-regex-italic)
4093 (markdown-cycle-italic))
4094 (t
4095 (error "Nothing to promote at point")))))
4096
4097 (defun markdown-demote ()
4098 "Either demote header or list item at point or cycle or remove markup.
4099 See `markdown-cycle-atx', `markdown-cycle-setext', and
4100 `markdown-demote-list-item'."
4101 (interactive)
4102 (let (bounds)
4103 (cond
4104 ;; Demote atx header
4105 ((thing-at-point-looking-at markdown-regex-header-atx)
4106 (markdown-cycle-atx 1))
4107 ;; Demote setext header
4108 ((thing-at-point-looking-at markdown-regex-header-setext)
4109 (markdown-cycle-setext 1))
4110 ;; Demote horizonal rule
4111 ((thing-at-point-looking-at markdown-regex-hr)
4112 (markdown-cycle-hr 1))
4113 ;; Demote list item
4114 ((setq bounds (markdown-cur-list-item-bounds))
4115 (markdown-demote-list-item))
4116 ;; Demote bold
4117 ((thing-at-point-looking-at markdown-regex-bold)
4118 (markdown-cycle-bold))
4119 ;; Demote italic
4120 ((thing-at-point-looking-at markdown-regex-italic)
4121 (markdown-cycle-italic))
4122 (t
4123 (error "Nothing to demote at point")))))
4124
4125 \f
4126 ;;; Commands ==================================================================
4127
4128 (defun markdown (&optional output-buffer-name)
4129 "Run `markdown-command' on buffer, sending output to OUTPUT-BUFFER-NAME.
4130 The output buffer name defaults to `markdown-output-buffer-name'.
4131 Return the name of the output buffer used."
4132 (interactive)
4133 (save-window-excursion
4134 (let ((begin-region)
4135 (end-region))
4136 (if (markdown-use-region-p)
4137 (setq begin-region (region-beginning)
4138 end-region (region-end))
4139 (setq begin-region (point-min)
4140 end-region (point-max)))
4141
4142 (unless output-buffer-name
4143 (setq output-buffer-name markdown-output-buffer-name))
4144
4145 (cond
4146 ;; Handle case when `markdown-command' does not read from stdin
4147 (markdown-command-needs-filename
4148 (if (not buffer-file-name)
4149 (error "Must be visiting a file")
4150 (shell-command (concat markdown-command " "
4151 (shell-quote-argument buffer-file-name))
4152 output-buffer-name)))
4153 ;; Pass region to `markdown-command' via stdin
4154 (t
4155 (shell-command-on-region begin-region end-region markdown-command
4156 output-buffer-name))))
4157 output-buffer-name))
4158
4159 (defun markdown-standalone (&optional output-buffer-name)
4160 "Special function to provide standalone HTML output.
4161 Insert the output in the buffer named OUTPUT-BUFFER-NAME."
4162 (interactive)
4163 (setq output-buffer-name (markdown output-buffer-name))
4164 (with-current-buffer output-buffer-name
4165 (set-buffer output-buffer-name)
4166 (goto-char (point-min))
4167 (unless (markdown-output-standalone-p)
4168 (markdown-add-xhtml-header-and-footer output-buffer-name))
4169 (html-mode))
4170 output-buffer-name)
4171
4172 (defun markdown-other-window (&optional output-buffer-name)
4173 "Run `markdown-command' on current buffer and display in other window.
4174 When OUTPUT-BUFFER-NAME is given, insert the output in the buffer with
4175 that name."
4176 (interactive)
4177 (display-buffer (markdown-standalone output-buffer-name)))
4178
4179 (defun markdown-output-standalone-p ()
4180 "Determine whether `markdown-command' output is standalone XHTML.
4181 Standalone XHTML output is identified by an occurrence of
4182 `markdown-xhtml-standalone-regexp' in the first five lines of output."
4183 (re-search-forward
4184 markdown-xhtml-standalone-regexp
4185 (save-excursion (goto-char (point-min)) (forward-line 4) (point))
4186 t))
4187
4188 (defun markdown-add-xhtml-header-and-footer (title)
4189 "Wrap XHTML header and footer with given TITLE around current buffer."
4190 (insert "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"
4191 "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"\n"
4192 "\t\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n\n"
4193 "<html xmlns=\"http://www.w3.org/1999/xhtml\">\n\n"
4194 "<head>\n<title>")
4195 (insert title)
4196 (insert "</title>\n")
4197 (when (> (length markdown-content-type) 0)
4198 (insert
4199 (format
4200 "<meta http-equiv=\"Content-Type\" content=\"%s;charset=%s\"/>\n"
4201 markdown-content-type
4202 (or (and markdown-coding-system
4203 (fboundp 'coding-system-get)
4204 (coding-system-get markdown-coding-system
4205 'mime-charset))
4206 (and (fboundp 'coding-system-get)
4207 (coding-system-get buffer-file-coding-system
4208 'mime-charset))
4209 "iso-8859-1"))))
4210 (if (> (length markdown-css-path) 0)
4211 (insert "<link rel=\"stylesheet\" type=\"text/css\" media=\"all\" href=\""
4212 markdown-css-path
4213 "\" />\n"))
4214 (when (> (length markdown-xhtml-header-content) 0)
4215 (insert markdown-xhtml-header-content))
4216 (insert "\n</head>\n\n"
4217 "<body>\n\n")
4218 (goto-char (point-max))
4219 (insert "\n"
4220 "</body>\n"
4221 "</html>\n"))
4222
4223 (defun markdown-preview (&optional output-buffer-name)
4224 "Run `markdown-command' on the current buffer and view output in browser.
4225 When OUTPUT-BUFFER-NAME is given, insert the output in the buffer with
4226 that name."
4227 (interactive)
4228 (browse-url-of-buffer (markdown markdown-output-buffer-name)))
4229
4230 (defun markdown-export-file-name (&optional extension)
4231 "Attempt to generate a filename for Markdown output.
4232 The file extension will be EXTENSION if given, or .html by default.
4233 If the current buffer is visiting a file, we construct a new
4234 output filename based on that filename. Otherwise, return nil."
4235 (when (buffer-file-name)
4236 (unless extension
4237 (setq extension ".html"))
4238 (concat
4239 (cond
4240 ((buffer-file-name)
4241 (file-name-sans-extension (buffer-file-name)))
4242 (t (buffer-name)))
4243 extension)))
4244
4245 (defun markdown-export (&optional output-file)
4246 "Run Markdown on the current buffer, save to file, and return the filename.
4247 If OUTPUT-FILE is given, use that as the filename. Otherwise, use the filename
4248 generated by `markdown-export-file-name', which will be constructed using the
4249 current filename, but with the extension removed and replaced with .html."
4250 (interactive)
4251 (unless output-file
4252 (setq output-file (markdown-export-file-name ".html")))
4253 (when output-file
4254 (let* ((init-buf (current-buffer))
4255 (init-point (point))
4256 (init-buf-string (buffer-string))
4257 (output-buffer (find-file-noselect output-file))
4258 (output-buffer-name (buffer-name output-buffer)))
4259 (run-hooks 'markdown-before-export-hook)
4260 (markdown-standalone output-buffer-name)
4261 (with-current-buffer output-buffer
4262 (run-hooks 'markdown-after-export-hook)
4263 (save-buffer))
4264 ;; if modified, restore initial buffer
4265 (when (buffer-modified-p init-buf)
4266 (erase-buffer)
4267 (insert init-buf-string)
4268 (save-buffer)
4269 (goto-char init-point))
4270 output-file)))
4271
4272 (defun markdown-export-and-preview ()
4273 "Export to XHTML using `markdown-export' and browse the resulting file."
4274 (interactive)
4275 (browse-url (markdown-export)))
4276
4277 (defun markdown-open ()
4278 "Open file for the current buffer with `markdown-open-command'."
4279 (interactive)
4280 (if (not markdown-open-command)
4281 (error "Variable `markdown-open-command' must be set")
4282 (if (not buffer-file-name)
4283 (error "Must be visiting a file")
4284 (call-process markdown-open-command
4285 nil nil nil buffer-file-name))))
4286
4287 (defun markdown-kill-ring-save ()
4288 "Run Markdown on file and store output in the kill ring."
4289 (interactive)
4290 (save-window-excursion
4291 (markdown)
4292 (with-current-buffer markdown-output-buffer-name
4293 (kill-ring-save (point-min) (point-max)))))
4294
4295 \f
4296 ;;; Links =====================================================================
4297
4298 (defun markdown-link-p ()
4299 "Return non-nil when `point' is at a non-wiki link.
4300 See `markdown-wiki-link-p' for more information."
4301 (let ((case-fold-search nil))
4302 (and (not (markdown-wiki-link-p))
4303 (or (thing-at-point-looking-at markdown-regex-link-inline)
4304 (thing-at-point-looking-at markdown-regex-link-reference)
4305 (thing-at-point-looking-at markdown-regex-uri)
4306 (thing-at-point-looking-at markdown-regex-angle-uri)))))
4307
4308 (defun markdown-link-link ()
4309 "Return the link part of the regular (non-wiki) link at point.
4310 Works with both inline and reference style links. If point is
4311 not at a link or the link reference is not defined returns nil."
4312 (cond
4313 ((thing-at-point-looking-at markdown-regex-link-inline)
4314 (match-string-no-properties 5))
4315 ((thing-at-point-looking-at markdown-regex-link-reference)
4316 (let* ((text (match-string-no-properties 2))
4317 (reference (match-string-no-properties 4))
4318 (target (downcase (if (string= reference "[]") text reference))))
4319 (car (markdown-reference-definition target))))
4320 ((thing-at-point-looking-at markdown-regex-uri)
4321 (match-string-no-properties 0))
4322 ((thing-at-point-looking-at markdown-regex-angle-uri)
4323 (match-string-no-properties 2))
4324 (t nil)))
4325
4326 (defun markdown-follow-link-at-point ()
4327 "Open the current non-wiki link in a browser."
4328 (interactive)
4329 (if (markdown-link-p) (browse-url (markdown-link-link))
4330 (error "Point is not at a Markdown link or URI")))
4331
4332 \f
4333 ;;; WikiLink Following/Markup =================================================
4334
4335 (defun markdown-wiki-link-p ()
4336 "Return non-nil when `point' is at a true wiki link.
4337 A true wiki link name matches `markdown-regex-wiki-link' but does not
4338 match the current file name after conversion. This modifies the data
4339 returned by `match-data'. Note that the potential wiki link name must
4340 be available via `match-string'."
4341 (let ((case-fold-search nil))
4342 (and (thing-at-point-looking-at markdown-regex-wiki-link)
4343 (or (not buffer-file-name)
4344 (not (string-equal (buffer-file-name)
4345 (markdown-convert-wiki-link-to-filename
4346 (markdown-wiki-link-link)))))
4347 (not (save-match-data
4348 (save-excursion))))))
4349
4350 (defun markdown-wiki-link-link ()
4351 "Return the link part of the wiki link using current match data.
4352 The location of the link component depends on the value of
4353 `markdown-wiki-link-alias-first'."
4354 (if markdown-wiki-link-alias-first
4355 (or (match-string-no-properties 4) (match-string-no-properties 2))
4356 (match-string-no-properties 2)))
4357
4358 (defun markdown-wiki-link-alias ()
4359 "Return the alias or text part of the wiki link using current match data.
4360 The location of the alias component depends on the value of
4361 `markdown-wiki-link-alias-first'."
4362 (if markdown-wiki-link-alias-first
4363 (match-string-no-properties 2)
4364 (or (match-string-no-properties 4) (match-string-no-properties 2))))
4365
4366 (defun markdown-convert-wiki-link-to-filename (name)
4367 "Generate a filename from the wiki link NAME.
4368 Spaces in NAME are replaced with `markdown-link-space-sub-char'.
4369 When in `gfm-mode', follow GitHub's conventions where [[Test Test]]
4370 and [[test test]] both map to Test-test.ext."
4371 (let ((basename (markdown-replace-regexp-in-string
4372 "[[:space:]\n]" markdown-link-space-sub-char name)))
4373 (when (eq major-mode 'gfm-mode)
4374 (setq basename (concat (upcase (substring basename 0 1))
4375 (downcase (substring basename 1 nil)))))
4376 (concat basename
4377 (if (buffer-file-name)
4378 (concat "."
4379 (file-name-extension (buffer-file-name)))))))
4380
4381 (defun markdown-follow-wiki-link (name &optional other)
4382 "Follow the wiki link NAME.
4383 Convert the name to a file name and call `find-file'. Ensure that
4384 the new buffer remains in `markdown-mode'. Open the link in another
4385 window when OTHER is non-nil."
4386 (let ((filename (markdown-convert-wiki-link-to-filename name))
4387 (wp (file-name-directory buffer-file-name)))
4388 (when other (other-window 1))
4389 (find-file (concat wp filename)))
4390 (when (not (eq major-mode 'markdown-mode))
4391 (markdown-mode)))
4392
4393 (defun markdown-follow-wiki-link-at-point (&optional arg)
4394 "Find Wiki Link at point.
4395 With prefix argument ARG, open the file in other window.
4396 See `markdown-wiki-link-p' and `markdown-follow-wiki-link'."
4397 (interactive "P")
4398 (if (markdown-wiki-link-p)
4399 (markdown-follow-wiki-link (markdown-wiki-link-link) arg)
4400 (error "Point is not at a Wiki Link")))
4401
4402 (defun markdown-highlight-wiki-link (from to face)
4403 "Highlight the wiki link in the region between FROM and TO using FACE."
4404 (put-text-property from to 'font-lock-face face))
4405
4406 (defun markdown-unfontify-region-wiki-links (from to)
4407 "Remove wiki link faces from the region specified by FROM and TO."
4408 (interactive "nfrom: \nnto: ")
4409 (remove-text-properties from to '(font-lock-face markdown-link-face))
4410 (remove-text-properties from to '(font-lock-face markdown-missing-link-face)))
4411
4412 (defun markdown-fontify-region-wiki-links (from to)
4413 "Search region given by FROM and TO for wiki links and fontify them.
4414 If a wiki link is found check to see if the backing file exists
4415 and highlight accordingly."
4416 (goto-char from)
4417 (save-match-data
4418 (while (re-search-forward markdown-regex-wiki-link to t)
4419 (let ((highlight-beginning (match-beginning 1))
4420 (highlight-end (match-end 1))
4421 (file-name
4422 (markdown-convert-wiki-link-to-filename
4423 (markdown-wiki-link-link))))
4424 (if (file-exists-p file-name)
4425 (markdown-highlight-wiki-link
4426 highlight-beginning highlight-end markdown-link-face)
4427 (markdown-highlight-wiki-link
4428 highlight-beginning highlight-end markdown-link-face)
4429 (markdown-highlight-wiki-link
4430 highlight-beginning highlight-end markdown-missing-link-face))))))
4431
4432 (defun markdown-extend-changed-region (from to)
4433 "Extend region given by FROM and TO so that we can fontify all links.
4434 The region is extended to the first newline before and the first
4435 newline after."
4436 ;; start looking for the first new line before 'from
4437 (goto-char from)
4438 (re-search-backward "\n" nil t)
4439 (let ((new-from (point-min))
4440 (new-to (point-max)))
4441 (if (not (= (point) from))
4442 (setq new-from (point)))
4443 ;; do the same thing for the first new line after 'to
4444 (goto-char to)
4445 (re-search-forward "\n" nil t)
4446 (if (not (= (point) to))
4447 (setq new-to (point)))
4448 (values new-from new-to)))
4449
4450 (defun markdown-check-change-for-wiki-link (from to change)
4451 "Check region between FROM and TO for wiki links and re-fontfy as needed.
4452 Designed to be used with the `after-change-functions' hook.
4453 CHANGE is the number of bytes of pre-change text replaced by the
4454 given range."
4455 (interactive "nfrom: \nnto: \nnchange: ")
4456 (let* ((modified (buffer-modified-p))
4457 (buffer-undo-list t)
4458 (inhibit-read-only t)
4459 (inhibit-point-motion-hooks t)
4460 deactivate-mark
4461 buffer-file-truename)
4462 (unwind-protect
4463 (save-excursion
4464 (save-match-data
4465 (save-restriction
4466 ;; Extend the region to fontify so that it starts
4467 ;; and ends at safe places.
4468 (multiple-value-bind (new-from new-to)
4469 (markdown-extend-changed-region from to)
4470 ;; Unfontify existing fontification (start from scratch)
4471 (markdown-unfontify-region-wiki-links new-from new-to)
4472 ;; Now do the fontification.
4473 (markdown-fontify-region-wiki-links new-from new-to)))))
4474 (and (not modified)
4475 (buffer-modified-p)
4476 (set-buffer-modified-p nil)))))
4477
4478 (defun markdown-fontify-buffer-wiki-links ()
4479 "Refontify all wiki links in the buffer."
4480 (interactive)
4481 (markdown-check-change-for-wiki-link (point-min) (point-max) 0))
4482
4483 \f
4484 ;;; Following and Jumping =====================================================
4485
4486 (defun markdown-follow-thing-at-point (arg)
4487 "Follow thing at point if possible, such as a reference link or wiki link.
4488 Opens inline and reference links in a browser. Opens wiki links
4489 to other files in the current window, or the another window if
4490 ARG is non-nil.
4491 See `markdown-follow-link-at-point' and
4492 `markdown-follow-wiki-link-at-point'."
4493 (interactive "P")
4494 (cond ((markdown-link-p)
4495 (markdown-follow-link-at-point))
4496 ((markdown-wiki-link-p)
4497 (markdown-follow-wiki-link-at-point arg))
4498 (t
4499 (error "Nothing to follow at point"))))
4500
4501 (defun markdown-jump ()
4502 "Jump to another location based on context at point.
4503 Jumps between reference links and definitions; between footnote
4504 markers and footnote text."
4505 (interactive)
4506 (cond ((markdown-footnote-text-positions)
4507 (markdown-footnote-return))
4508 ((markdown-footnote-marker-positions)
4509 (markdown-footnote-goto-text))
4510 ((thing-at-point-looking-at markdown-regex-link-reference)
4511 (markdown-reference-goto-definition))
4512 ((thing-at-point-looking-at markdown-regex-reference-definition)
4513 (markdown-reference-goto-link (match-string-no-properties 1)))
4514 (t
4515 (error "Nothing to jump to from context at point"))))
4516
4517 \f
4518 ;;; Miscellaneous =============================================================
4519
4520 (defun markdown-compress-whitespace-string (str)
4521 "Compress whitespace in STR and return result.
4522 Leading and trailing whitespace is removed. Sequences of multiple
4523 spaces, tabs, and newlines are replaced with single spaces."
4524 (replace-regexp-in-string "\\(^[ \t\n]+\\|[ \t\n]+$\\)" ""
4525 (replace-regexp-in-string "[ \t\n]+" " " str)))
4526
4527 (defun markdown-line-number-at-pos (&optional pos)
4528 "Return (narrowed) buffer line number at position POS.
4529 If POS is nil, use current buffer location.
4530 This is an exact copy of `line-number-at-pos' for use in emacs21."
4531 (let ((opoint (or pos (point))) start)
4532 (save-excursion
4533 (goto-char (point-min))
4534 (setq start (point))
4535 (goto-char opoint)
4536 (forward-line 0)
4537 (1+ (count-lines start (point))))))
4538
4539 (defun markdown-nobreak-p ()
4540 "Return nil if it is acceptable to break the current line at the point."
4541 ;; inside in square brackets (e.g., link anchor text)
4542 (looking-back "\\[[^]]*"))
4543
4544 (defun markdown-adaptive-fill-function ()
4545 "Return prefix for filling paragraph or nil if not determined."
4546 (cond
4547 ;; List item inside blockquote
4548 ((looking-at "^[ \t]*>[ \t]*\\([0-9]+\\.\\|[*+-]\\)[ \t]+")
4549 (replace-regexp-in-string
4550 "[0-9\\.*+-]" " " (match-string-no-properties 0)))
4551 ;; dislines
4552 ((looking-at "^\\(@+[a-z,\"]+[[:space:]]\\)") (match-string-no-properties 0))
4553 ;; Blockquote
4554 ((looking-at "^[ \t]*>[ \t]*")
4555 (match-string-no-properties 0))
4556 ;; List items
4557 ((looking-at markdown-regex-list)
4558 (match-string-no-properties 0))
4559 ;; No match
4560 (t nil)))
4561
4562 \f
4563 ;;; Extensions ================================================================
4564
4565 (defun markdown-reload-extensions ()
4566 "Check settings, update font-lock keywords, and re-fontify buffer."
4567 (interactive)
4568 (when (eq major-mode 'markdown-mode)
4569 (setq markdown-mode-font-lock-keywords
4570 (append
4571 (when markdown-enable-math
4572 markdown-mode-font-lock-keywords-math)
4573 markdown-mode-font-lock-keywords-basic
4574 markdown-mode-font-lock-keywords-core))
4575 (setq font-lock-defaults '(markdown-mode-font-lock-keywords))
4576 (when (fboundp 'font-lock-refresh-defaults) (font-lock-refresh-defaults))))
4577
4578 (defun markdown-hide-other-langs (lang)
4579 "Hide All languages except `lang'"
4580 (interactive "sEnter language: ")
4581 (save-excursion
4582 (beginning-of-buffer)
4583 (while (re-search-forward "^@+\\([a-z,]+\\){[\0-\377[:nonascii:]]*?\n@+}.*$" nil t)
4584 (unless (string-match-p (regexp-quote lang) (match-string 1))
4585 (facemenu-set-invisible
4586 (match-beginning 0) (match-end 0)))
4587 ))
4588 (save-excursion
4589 (beginning-of-buffer)
4590 (while (re-search-forward "^@+\\([a-z,]+\\).*$" nil t)
4591 (message (match-string 1))
4592 (unless (string-match-p (regexp-quote lang) (match-string 1))
4593 (facemenu-set-invisible
4594 (match-beginning 0) (match-end 0)))
4595 )
4596 )
4597 )
4598
4599 (defun schreib-build ()
4600 (interactive)
4601 (shell-command "schreib b")
4602 )
4603 (defun schreib-deploy ()
4604 (interactive)
4605 (shell-command "schreib d")
4606 )
4607
4608 (defun markdown-unhide-langs ()
4609 "Revert `markdown-hide-other-langs'"
4610 (interactive)
4611 (facemenu-remove-special (point-min) (point-max))
4612 )
4613
4614 (defun markdown-enable-math (&optional arg)
4615 "Toggle support for inline and display LaTeX math expressions.
4616 With a prefix argument ARG, enable math mode if ARG is positive,
4617 and disable it otherwise. If called from Lisp, enable the mode
4618 if ARG is omitted or nil."
4619 (interactive (list (or current-prefix-arg 'toggle)))
4620 (setq markdown-enable-math
4621 (if (eq arg 'toggle)
4622 (not markdown-enable-math)
4623 (> (prefix-numeric-value arg) 0)))
4624 (if markdown-enable-math
4625 (message "markdown-mode math support enabled")
4626 (message "markdown-mode math support disabled"))
4627 (markdown-reload-extensions))
4628
4629 \f
4630 ;;; Mode Definition ==========================================================
4631
4632 (defun markdown-show-version ()
4633 "Show the version number in the minibuffer."
4634 (interactive)
4635 (message "markdown-mode, version %s" markdown-mode-version))
4636
4637 ;;;###autoload
4638 (define-derived-mode markdown-mode text-mode "Markdown"
4639 "Major mode for editing Markdown files."
4640 ;; Natural Markdown tab width
4641 (setq tab-width 4)
4642 ;; Comments
4643 (make-local-variable 'comment-start)
4644 (setq comment-start "<!-- ")
4645 (make-local-variable 'comment-end)
4646 (setq comment-end " -->")
4647 (make-local-variable 'comment-start-skip)
4648 (setq comment-start-skip "<!--[ \t]*")
4649 (make-local-variable 'comment-column)
4650 (setq comment-column 0)
4651 (set (make-local-variable 'comment-auto-fill-only-comments) nil)
4652 ;; Font lock.
4653 (set (make-local-variable 'markdown-mode-font-lock-keywords) nil)
4654 (set (make-local-variable 'font-lock-defaults) nil)
4655 (set (make-local-variable 'font-lock-multiline) t)
4656 (markdown-reload-extensions)
4657 ;; Extensions
4658 (make-local-variable 'markdown-enable-math)
4659 (add-hook 'hack-local-variables-hook 'markdown-reload-extensions)
4660 ;; For imenu support
4661 (setq imenu-create-index-function 'markdown-imenu-create-index)
4662 ;; For menu support in XEmacs
4663 (easy-menu-add markdown-mode-menu markdown-mode-map)
4664 ;; Defun movement
4665 (set (make-local-variable 'beginning-of-defun-function)
4666 'markdown-beginning-of-defun)
4667 (set (make-local-variable 'end-of-defun-function)
4668 'markdown-end-of-defun)
4669 ;; Paragraph filling
4670 ;; (set (make-local-variable 'paragraph-start)
4671 ;; "\f\\|[ \t]*$\\|[ \t]*[*+-] \\|[ \t]*[0-9]+\\.[ \t]\\|[ \t]*: ")
4672 (set
4673 ; Should match start of lines that start or separate paragraphs
4674 (make-local-variable 'paragraph-start)
4675 (mapconcat 'identity
4676 '(
4677 "\f" ; starts with a literal line-feed
4678 "[ \t\f]*$" ; space-only line
4679 "[ \t]*[*+-][ \t]+" ; unordered list item
4680 "[ \t]*\\(?:[0-9]+\\|#\\)\\.[ \t]+" ; ordered list item
4681 "[ \t]*\\[\\S-*\\]:[ \t]+" ; link ref def
4682 "[ \t]*:[ \t]+" ; definition
4683 "@+[a-z,]+{" ; dislines block start
4684 ; "@+[\"a-z,]+" ; dislines line
4685 )
4686 "\\|"))
4687 (set
4688 ; Should match lines that separate paragraphs without being
4689 ; part of any paragraph:
4690 (make-local-variable 'paragraph-separate)
4691 (mapconcat 'identity
4692 '("[ \t\f]*$" ; space-only line
4693 ; The following is not ideal, but the Fill customization
4694 ; options really only handle paragraph-starting prefixes,
4695 ; not paragraph-ending suffixes:
4696 ".* $" ; line ending in two spaces
4697 "^@}" ; Dislines ending
4698 "[ \t]*\\[\\^\\S-*\\]:[ \t]*$") ; just the start of a footnote def
4699
4700 "\\|"))
4701
4702 ;; (set (make-local-variable 'paragraph-separate)
4703 ;; "\\(?:[ \t\f]*\\|.* \\)$")
4704 (set (make-local-variable 'adaptive-fill-first-line-regexp)
4705 "\\`[ \t]*>[ \t]*?\\'\\|^\\(@+[a-z,\"]+[[:space:]]\\)")
4706 (set (make-local-variable 'adaptive-fill-function)
4707 'markdown-adaptive-fill-function)
4708 ;; Outline mode
4709 (make-local-variable 'outline-regexp)
4710 (setq outline-regexp markdown-regex-header)
4711 (make-local-variable 'outline-level)
4712 (setq outline-level 'markdown-outline-level)
4713 ;; Cause use of ellipses for invisible text.
4714 (add-to-invisibility-spec '(outline . t))
4715 ;; Indentation and filling
4716 (make-local-variable 'fill-nobreak-predicate)
4717 (add-hook 'fill-nobreak-predicate 'markdown-nobreak-p)
4718 (setq indent-line-function markdown-indent-function)
4719
4720 ;; Prepare hooks for XEmacs compatibility
4721 (when (featurep 'xemacs)
4722 (make-local-hook 'after-change-functions)
4723 (make-local-hook 'font-lock-extend-region-functions)
4724 (make-local-hook 'window-configuration-change-hook))
4725
4726 ;; Multiline font lock
4727 (add-hook 'font-lock-extend-region-functions
4728 'markdown-font-lock-extend-region)
4729
4730 ;; Anytime text changes make sure it gets fontified correctly
4731 (add-hook 'after-change-functions 'markdown-check-change-for-wiki-link t t)
4732
4733 ;; If we left the buffer there is a really good chance we were
4734 ;; creating one of the wiki link documents. Make sure we get
4735 ;; refontified when we come back.
4736 (add-hook 'window-configuration-change-hook
4737 'markdown-fontify-buffer-wiki-links t t)
4738
4739 ;; do the initial link fontification
4740 (markdown-fontify-buffer-wiki-links))
4741
4742 ;;;###autoload(add-to-list 'auto-mode-alist '("\\.markdown\\'" . markdown-mode))
4743 ;;;###autoload(add-to-list 'auto-mode-alist '("\\.md\\'" . markdown-mode))
4744 ;;;###autoload(add-to-list 'auto-mode-alist '("\\.text\\'" . markdown-mode))
4745
4746 \f
4747 ;;; GitHub Flavored Markdown Mode ============================================
4748
4749 (defvar gfm-font-lock-keywords
4750 (append
4751 ;; GFM features to match first
4752 (list
4753 (cons 'markdown-match-gfm-code-blocks '((1 markdown-pre-face)
4754 (2 markdown-language-keyword-face t t)
4755 (3 markdown-pre-face)
4756 (4 markdown-pre-face))))
4757 ;; Basic Markdown features (excluding possibly overridden ones)
4758 markdown-mode-font-lock-keywords-basic
4759 ;; GFM features to match last
4760 (list
4761 (cons markdown-regex-gfm-italic '(2 markdown-italic-face))))
4762 "Default highlighting expressions for GitHub Flavored Markdown mode.")
4763
4764 ;;;###autoload
4765 (define-derived-mode gfm-mode markdown-mode "GFM"
4766 "Major mode for editing GitHub Flavored Markdown files."
4767 (setq markdown-link-space-sub-char "-")
4768 (set (make-local-variable 'font-lock-defaults)
4769 '(gfm-font-lock-keywords))
4770 (auto-fill-mode 0)
4771 ;; Use visual-line-mode if available, fall back to longlines-mode:
4772 (cond ((fboundp 'visual-line-mode)
4773 (visual-line-mode 1))
4774 ((fboundp 'longlines-mode)
4775 (longlines-mode 1)))
4776 ;; do the initial link fontification
4777 (markdown-fontify-buffer-wiki-links))
4778
4779 \f