Advertisement
Guest User

markdown-mode with linkd-style links

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