PageRenderTime 29ms CodeModel.GetById 51ms RepoModel.GetById 0ms app.codeStats 1ms

/vendor/markdown-mode.el

http://github.com/rejeep/emacs
Emacs Lisp | 1469 lines | 930 code | 208 blank | 331 comment | 88 complexity | ac1aea4ec1db395bdc9fff72ebcd3168 MD5 | raw file
Possible License(s): GPL-2.0
  1. ;;; markdown-mode.el --- Major mode to edit Markdown files in Emacs
  2. ;; Copyright (C) 2007, 2008, 2009 Jason Blevins
  3. ;; Version: 1.7
  4. ;; Keywords: Markdown major mode
  5. ;; Author: Jason Blevins <jrblevin@sdf.lonestar.org>
  6. ;; URL: http://jblevins.org/projects/markdown-mode/
  7. ;; This file is not part of GNU Emacs.
  8. ;; This program is free software; you can redistribute it and/or modify
  9. ;; it under the terms of the GNU General Public License as published by
  10. ;; the Free Software Foundation; either version 2, or (at your option)
  11. ;; any later version.
  12. ;; This program is distributed in the hope that it will be useful,
  13. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. ;; GNU General Public License for more details.
  16. ;; You should have received a copy of the GNU General Public License
  17. ;; along with this program; if not, write to the Free Software
  18. ;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19. ;;; Commentary:
  20. ;; markdown-mode is a major mode for editing [Markdown][]-formatted
  21. ;; text files in GNU Emacs. markdown-mode is free software, licensed
  22. ;; under the GNU GPL.
  23. ;;
  24. ;; [Markdown]: http://daringfireball.net/projects/markdown/
  25. ;;
  26. ;; The latest stable version is markdown-mode 1.7, released on October 1, 2009:
  27. ;;
  28. ;; * [markdown-mode.el][]
  29. ;; * [Screenshot][]
  30. ;; * [Release notes][]
  31. ;;
  32. ;; markdown-mode is also available in the Debian
  33. ;; [emacs-goodies-el](http://packages.debian.org/emacs-goodies-el)
  34. ;; package (beginning with revision 27.0-1) and the OpenBSD
  35. ;; [textproc/markdown-mode](http://pkgsrc.se/textproc/markdown-mode) package.
  36. ;;
  37. ;; [markdown-mode.el]: http://jblevins.org/projects/markdown-mode/markdown-mode.el
  38. ;; [screenshot]: http://jblevins.org/projects/markdown-mode/screenshots/20080604-001.png
  39. ;; [release notes]: http://jblevins.org/projects/markdown-mode/rev-1-7
  40. ;; The latest development version can be downloaded directly
  41. ;; ([markdown-mode.el][devel.el]) or it can be obtained from the
  42. ;; (browsable and clonable) Git repository at
  43. ;; <http://jblevins.org/git/markdown-mode.git>. The entire repository,
  44. ;; including the full project history, can be cloned via the Git protocol
  45. ;; by running
  46. ;;
  47. ;; git clone git://jblevins.org/git/markdown-mode.git
  48. ;;
  49. ;; [devel.el]: http://jblevins.org/git/markdown-mode.git/plain/markdown-mode.el
  50. ;;; Dependencies:
  51. ;; markdown-mode requires easymenu, a standard package since GNU Emacs
  52. ;; 19 and XEmacs 19, which provides a uniform interface for creating
  53. ;; menus in GNU Emacs and XEmacs.
  54. ;;; Installation:
  55. ;; Make sure to place `markdown-mode.el` somewhere in the load-path and add
  56. ;; the following lines to your `.emacs` file to associate markdown-mode
  57. ;; with `.text` files:
  58. ;;
  59. ;; (autoload 'markdown-mode "markdown-mode.el"
  60. ;; "Major mode for editing Markdown files" t)
  61. ;; (setq auto-mode-alist
  62. ;; (cons '("\\.text" . markdown-mode) auto-mode-alist))
  63. ;;
  64. ;; There is no consensus on an official file extension so change `.text` to
  65. ;; `.mdwn`, `.md`, `.mdt`, or whatever you call your markdown files.
  66. ;;; Customization:
  67. ;; Although no configuration is *necessary* there are a few things
  68. ;; that can be customized. The `M-x customize-mode` command
  69. ;; provides an interface to all of the possible customizations:
  70. ;;
  71. ;; * `markdown-command` - the command used to run Markdown
  72. ;; (default: `markdown`).
  73. ;;
  74. ;; * `markdown-hr-length` - the length of horizontal rules
  75. ;; (default: `5`).
  76. ;;
  77. ;; * `markdown-bold-underscore` - set to a non-nil value to use two
  78. ;; underscores for bold instead of two asterisks (default: `nil`).
  79. ;;
  80. ;; * `markdown-italic-underscore` - set to a non-nil value to use
  81. ;; underscores for italic instead of asterisks (default: `nil`).
  82. ;;
  83. ;; * `markdown-indent-function` - the function to use for automatic
  84. ;; indentation (default: `markdown-indent-line`).
  85. ;;
  86. ;; * `markdown-indent-on-enter` - set to a non-nil value to
  87. ;; automatically indent new lines when the enter key is pressed
  88. ;; (default: `t`)
  89. ;;
  90. ;; * `markdown-uri-types` - a list of protocols for URIs that
  91. ;; `markdown-mode' should highlight.
  92. ;;
  93. ;; * `markdown-enable-math` - syntax highlighting for
  94. ;; LaTeX fragments (default: `nil`).
  95. ;;
  96. ;; Additionally, the faces used for syntax highlighting can be modified to
  97. ;; your liking by issuing `M-x customize-group RET markdown-faces`
  98. ;; or by using the "Markdown Faces" link at the bottom of the mode
  99. ;; customization screen.
  100. ;;; Usage:
  101. ;; Keybindings are grouped by prefixes based on their function. For
  102. ;; example, commands dealing with headers begin with `C-c C-t`. The
  103. ;; primary commands in each group will are described below. You can
  104. ;; obtain a list of all keybindings by pressing `C-c C-h`.
  105. ;;
  106. ;; * Anchors: `C-c C-a`
  107. ;;
  108. ;; `C-c C-a l` inserts inline links of the form `[text](url)`. If
  109. ;; there is an active region, text in the region is used for the
  110. ;; link text. `C-c C-a w` acts similarly for wiki links of the
  111. ;; form `[[WikiLink]]`.
  112. ;;
  113. ;; * Commands: `C-c C-c`
  114. ;;
  115. ;; `C-c C-c m` will run Markdown on the current buffer and preview
  116. ;; the output in another buffer while `C-c C-c p` runs Markdown on
  117. ;; the current buffer and previews the output in a browser.
  118. ;;
  119. ;; `C-c C-c c` will check for undefined references. If there are
  120. ;; any, a small buffer will open with a list of undefined
  121. ;; references and the line numbers on which they appear. In Emacs
  122. ;; 22 and greater, selecting a reference from this list and
  123. ;; pressing `RET` will insert an empty reference definition at the
  124. ;; end of the buffer. Similarly, selecting the line number will
  125. ;; jump to the corresponding line.
  126. ;;
  127. ;; * Images: `C-c C-i`
  128. ;;
  129. ;; `C-c C-i i` inserts an image, using the active region (if any)
  130. ;; as the alt text.
  131. ;;
  132. ;; * Physical styles: `C-c C-p`
  133. ;;
  134. ;; These commands all act on text in the active region, if any,
  135. ;; and insert empty markup fragments otherwise. `C-c C-p b` makes
  136. ;; the selected text bold, `C-c C-p f` formats the region as
  137. ;; fixed-width text, and `C-c C-p i` is used for italic text.
  138. ;;
  139. ;; * Logical styles: `C-c C-s`
  140. ;;
  141. ;; These commands all act on text in the active region, if any,
  142. ;; and insert empty markup fragments otherwise. Logical styles
  143. ;; include blockquote (`C-c C-s b`), preformatted (`C-c C-s p`),
  144. ;; code (`C-c C-s c`), emphasis (`C-c C-s e`), and strong (`C-c
  145. ;; C-s s`).
  146. ;;
  147. ;; * Headers: `C-c C-t`
  148. ;;
  149. ;; All header commands use text in the active region, if any, as
  150. ;; the header text. To insert an atx or hash style level-n
  151. ;; header, press `C-c C-t n` where n is between 1 and 6. For a
  152. ;; top-level setext or underline style header press `C-c C-t t`
  153. ;; (mnemonic: title) and for a second-level underline-style header
  154. ;; press `C-c C-t s` (mnemonic: section).
  155. ;;
  156. ;; * Other commands
  157. ;;
  158. ;; `C-c -` inserts a horizontal rule.
  159. ;;
  160. ;; Many of the commands described above behave differently depending on
  161. ;; whether Transient Mark mode is enabled or not. When it makes sense,
  162. ;; if Transient Mark mode is on and a region is active, the command
  163. ;; applies to the text in the region (e.g., `C-c C-p b` makes the region
  164. ;; bold). For users who prefer to work outside of Transient Mark mode,
  165. ;; in Emacs 22 it can be enabled temporarily by pressing `C-SPC C-SPC`.
  166. ;;
  167. ;; When applicable, commands that specifically act on the region even
  168. ;; outside of Transient Mark mode have the same keybinding as the with
  169. ;; the exception of an additional `C-` prefix. For example,
  170. ;; `markdown-insert-blockquote` is bound to `C-c C-s b` and only acts on
  171. ;; the region in Transient Mark mode while `markdown-blockquote-region`
  172. ;; is bound to `C-c C-s C-b` and always applies to the region (when
  173. ;; nonempty).
  174. ;;
  175. ;; markdown-mode supports outline-minor-mode as well as org-mode-style
  176. ;; visibility cycling for atx- or hash-style headers. There are two
  177. ;; types of visibility cycling: Pressing `S-TAB` cycles globally between
  178. ;; the table of contents view (headers only), outline view (top-level
  179. ;; headers only), and the full document view. Pressing `TAB` while the
  180. ;; point is at a header will cycle through levels of visibility for the
  181. ;; subtree: completely folded, visible children, and fully visible.
  182. ;; Note that mixing hash and underline style headers will give undesired
  183. ;; results.
  184. ;;; Extensions:
  185. ;; Besides supporting the basic Markdown syntax, markdown-mode also
  186. ;; includes syntax highlighting for `[[Wiki Links]]` by default.
  187. ;;
  188. ;; [SmartyPants][] support is possible by customizing `markdown-command`.
  189. ;; If you install `SmartyPants.pl` at, say, `/usr/local/bin/smartypants`,
  190. ;; then you can set `markdown-command` to `"markdown | smartypants"`.
  191. ;; You can do this either by using `M-x customize-group markdown`
  192. ;; or by placing the following in your `.emacs` file:
  193. ;;
  194. ;; (defun markdown-custom ()
  195. ;; "markdown-mode-hook"
  196. ;; (setq markdown-command "markdown | smartypants"))
  197. ;; (add-hook 'markdown-mode-hook '(lambda() (markdown-custom)))
  198. ;;
  199. ;; [SmartyPants]: http://daringfireball.net/projects/smartypants/
  200. ;;
  201. ;; Experimental syntax highlighting for mathematical expressions written
  202. ;; in LaTeX (only expressions denoted by `$..$`, `$$..$$`, or `\[..\]`)
  203. ;; can be enabled by setting `markdown-enable-math` to a non-nil value,
  204. ;; either via customize or by placing `(setq markdown-enable-itex t)`
  205. ;; in `.emacs`, and restarting Emacs.
  206. ;;; Acknowledgments:
  207. ;; markdown-mode has benefited greatly from the efforts of the
  208. ;; following people:
  209. ;;
  210. ;; * Cyril Brulebois <cyril.brulebois@enst-bretagne.fr> for Debian packaging.
  211. ;; * Conal Elliott <conal@conal.net> for a font-lock regexp patch.
  212. ;; * Edward O'Connor <hober0@gmail.com> for a font-lock regexp fix.
  213. ;; * Greg Bognar <greg_bognar@hms.harvard.edu> for menus and a patch.
  214. ;; * Daniel Burrows <dburrows@debian.org> for filing Debian bug #456592.
  215. ;; * Peter S. Galbraith <psg@debian.org> for maintaining emacs-goodies-el.
  216. ;; * Dmitry Dzhus <mail@sphinx.net.ru> for reference checking functions.
  217. ;; * Bryan Kyle <bryan.kyle@gmail.com> for indentation code.
  218. ;; * intrigeri <intrigeri@boum.org> for face customizations.
  219. ;; * Ankit Solanki <ankit.solanki@gmail.com> for longlines.el compatibility.
  220. ;; * Hilko Bengen <bengen@debian.org> for proper XHTML output.
  221. ;; * Jose A. Ortega Ruiz <jao@gnu.org> for Emacs 23 fixes.
  222. ;; * Alec Resnick <alec@sproutward.org> for bug reports.
  223. ;; * Peter Williams <pezra@barelyenough.org> for fill-paragraph enhancements.
  224. ;;; Bugs:
  225. ;; Although markdown-mode is developed and tested primarily using
  226. ;; GNU Emacs 23, compatibility with GNU Emacs 21 and 22 is also a
  227. ;; priority.
  228. ;;
  229. ;; markdown-mode's syntax highlighting is accomplished using the
  230. ;; search-based fontification features of Emacs through a series of
  231. ;; regular expressions. Unfortunately, Emacs has trouble highlighting
  232. ;; multi-line constructs using regular expressions and this creates
  233. ;; several syntax-highlighting quirks such as mistaking indented
  234. ;; lists for preformatted text, etc. Making markdown-mode's syntax
  235. ;; highlighting more robust through the use of matching functions
  236. ;; or syntactic font lock is a high-priority item for future work.
  237. ;;
  238. ;; If you find any bugs not mentioned here, please construct a test
  239. ;; case and/or a patch and email me at <jrblevin@sdf.lonestar.org>.
  240. ;;; History:
  241. ;; markdown-mode was written and is maintained by Jason Blevins. The
  242. ;; first version was released on May 24, 2007.
  243. ;;
  244. ;; * 2007-05-24: Version 1.1
  245. ;; * 2007-05-25: Version 1.2
  246. ;; * 2007-06-05: [Version 1.3][]
  247. ;; * 2007-06-29: Version 1.4
  248. ;; * 2008-05-24: [Version 1.5][]
  249. ;; * 2008-06-04: [Version 1.6][]
  250. ;; * 2008-10-01: [Version 1.7][]
  251. ;;
  252. ;; [Version 1.3]: http://jblevins.org/projects/markdown-mode/rev-1-3
  253. ;; [Version 1.5]: http://jblevins.org/projects/markdown-mode/rev-1-5
  254. ;; [Version 1.6]: http://jblevins.org/projects/markdown-mode/rev-1-6
  255. ;; [Version 1.7]: http://jblevins.org/projects/markdown-mode/rev-1-7
  256. ;;; Code:
  257. (require 'easymenu)
  258. (require 'outline)
  259. ;;; Customizable variables ====================================================
  260. ;; Current revision
  261. (defconst markdown-mode-version "1.7-dev")
  262. ;; A hook for users to run their own code when the mode is loaded.
  263. (defvar markdown-mode-hook nil)
  264. ;;; Customizable variables ====================================================
  265. (defgroup markdown nil
  266. "Major mode for editing text files in Markdown format."
  267. :prefix "markdown-"
  268. :group 'wp
  269. :link '(url-link "http://jblevins.org/projects/markdown-mode/"))
  270. (defcustom markdown-command "markdown"
  271. "Command to run markdown."
  272. :group 'markdown
  273. :type 'string)
  274. (defcustom markdown-hr-length 5
  275. "Length of horizonal rules."
  276. :group 'markdown
  277. :type 'integer)
  278. (defcustom markdown-bold-underscore nil
  279. "Use two underscores for bold instead of two asterisks."
  280. :group 'markdown
  281. :type 'boolean)
  282. (defcustom markdown-italic-underscore nil
  283. "Use underscores for italic instead of asterisks."
  284. :group 'markdown
  285. :type 'boolean)
  286. (defcustom markdown-indent-function 'markdown-indent-line
  287. "Function to use to indent."
  288. :group 'markdown
  289. :type 'function)
  290. (defcustom markdown-indent-on-enter t
  291. "Automatically indent new lines when enter key is pressed."
  292. :group 'markdown
  293. :type 'boolean)
  294. (defcustom markdown-uri-types
  295. '("acap" "cid" "data" "dav" "fax" "file" "ftp" "gopher" "http" "https"
  296. "imap" "ldap" "mailto" "mid" "modem" "news" "nfs" "nntp" "pop" "prospero"
  297. "rtsp" "service" "sip" "tel" "telnet" "tip" "urn" "vemmi" "wais")
  298. "Link types for syntax highlighting of URIs."
  299. :group 'markdown
  300. :type 'list)
  301. (defcustom markdown-enable-math nil
  302. "Syntax highlighting for inline LaTeX expressions.
  303. This will not take effect until Emacs is restarted."
  304. :group 'markdown
  305. :type 'boolean)
  306. (defcustom markdown-css-path nil
  307. "CSS file to include in the output XHTML"
  308. :group 'markdown
  309. :type 'string)
  310. ;;; Font lock =================================================================
  311. (require 'font-lock)
  312. (defvar markdown-italic-face 'markdown-italic-face
  313. "Face name to use for italic text.")
  314. (defvar markdown-bold-face 'markdown-bold-face
  315. "Face name to use for bold text.")
  316. (defvar markdown-header-face 'markdown-header-face
  317. "Face name to use as a base for headers.")
  318. (defvar markdown-header-face-1 'markdown-header-face-1
  319. "Face name to use for level-1 headers.")
  320. (defvar markdown-header-face-2 'markdown-header-face-2
  321. "Face name to use for level-2 headers.")
  322. (defvar markdown-header-face-3 'markdown-header-face-3
  323. "Face name to use for level-3 headers.")
  324. (defvar markdown-header-face-4 'markdown-header-face-4
  325. "Face name to use for level-4 headers.")
  326. (defvar markdown-header-face-5 'markdown-header-face-5
  327. "Face name to use for level-5 headers.")
  328. (defvar markdown-header-face-6 'markdown-header-face-6
  329. "Face name to use for level-6 headers.")
  330. (defvar markdown-inline-code-face 'markdown-inline-code-face
  331. "Face name to use for inline code.")
  332. (defvar markdown-list-face 'markdown-list-face
  333. "Face name to use for list markers.")
  334. (defvar markdown-blockquote-face 'markdown-blockquote-face
  335. "Face name to use for blockquote.")
  336. (defvar markdown-pre-face 'markdown-pre-face
  337. "Face name to use for preformatted text.")
  338. (defvar markdown-link-face 'markdown-link-face
  339. "Face name to use for links.")
  340. (defvar markdown-reference-face 'markdown-reference-face
  341. "Face name to use for reference.")
  342. (defvar markdown-url-face 'markdown-url-face
  343. "Face name to use for URLs.")
  344. (defvar markdown-link-title-face 'markdown-link-title-face
  345. "Face name to use for reference link titles.")
  346. (defvar markdown-comment-face 'markdown-comment-face
  347. "Face name to use for HTML comments.")
  348. (defvar markdown-math-face 'markdown-math-face
  349. "Face name to use for LaTeX expressions.")
  350. (defgroup markdown-faces nil
  351. "Faces used in Markdown Mode"
  352. :group 'markdown
  353. :group 'faces)
  354. (defface markdown-italic-face
  355. '((t :inherit font-lock-variable-name-face :italic t))
  356. "Face for italic text."
  357. :group 'markdown-faces)
  358. (defface markdown-bold-face
  359. '((t :inherit font-lock-variable-name-face :bold t))
  360. "Face for bold text."
  361. :group 'markdown-faces)
  362. (defface markdown-header-face
  363. '((t :inherit font-lock-function-name-face :weight bold))
  364. "Base face for headers."
  365. :group 'markdown-faces)
  366. (defface markdown-header-face-1
  367. '((t :inherit markdown-header-face))
  368. "Face for level-1 headers."
  369. :group 'markdown-faces)
  370. (defface markdown-header-face-2
  371. '((t :inherit markdown-header-face))
  372. "Face for level-2 headers."
  373. :group 'markdown-faces)
  374. (defface markdown-header-face-3
  375. '((t :inherit markdown-header-face))
  376. "Face for level-3 headers."
  377. :group 'markdown-faces)
  378. (defface markdown-header-face-4
  379. '((t :inherit markdown-header-face))
  380. "Face for level-4 headers."
  381. :group 'markdown-faces)
  382. (defface markdown-header-face-5
  383. '((t :inherit markdown-header-face))
  384. "Face for level-5 headers."
  385. :group 'markdown-faces)
  386. (defface markdown-header-face-6
  387. '((t :inherit markdown-header-face))
  388. "Face for level-6 headers."
  389. :group 'markdown-faces)
  390. (defface markdown-inline-code-face
  391. '((t :inherit font-lock-constant-face))
  392. "Face for inline code."
  393. :group 'markdown-faces)
  394. (defface markdown-list-face
  395. '((t :inherit font-lock-builtin-face))
  396. "Face for list item markers."
  397. :group 'markdown-faces)
  398. (defface markdown-blockquote-face
  399. '((t :inherit font-lock-doc-face))
  400. "Face for blockquote sections."
  401. :group 'markdown-faces)
  402. (defface markdown-pre-face
  403. '((t :inherit font-lock-constant-face))
  404. "Face for preformatted text."
  405. :group 'markdown-faces)
  406. (defface markdown-link-face
  407. '((t :inherit font-lock-keyword-face))
  408. "Face for links."
  409. :group 'markdown-faces)
  410. (defface markdown-reference-face
  411. '((t :inherit font-lock-type-face))
  412. "Face for link references."
  413. :group 'markdown-faces)
  414. (defface markdown-url-face
  415. '((t :inherit font-lock-string-face))
  416. "Face for URLs."
  417. :group 'markdown-faces)
  418. (defface markdown-link-title-face
  419. '((t :inherit font-lock-comment-face))
  420. "Face for reference link titles."
  421. :group 'markdown-faces)
  422. (defface markdown-comment-face
  423. '((t :inherit font-lock-comment-face))
  424. "Face for HTML comments."
  425. :group 'markdown-faces)
  426. (defface markdown-math-face
  427. '((t :inherit font-lock-string-face))
  428. "Face for LaTeX expressions."
  429. :group 'markdown-faces)
  430. (defconst markdown-regex-link-inline
  431. "\\(!?\\[[^]]*?\\]\\)\\(([^\\)]*)\\)"
  432. "Regular expression for a [text](file) or an image link ![text](file).")
  433. (defconst markdown-regex-link-reference
  434. "\\(!?\\[[^]]+?\\]\\)[ ]?\\(\\[[^]]*?\\]\\)"
  435. "Regular expression for a reference link [text][id].")
  436. (defconst markdown-regex-reference-definition
  437. "^ \\{0,3\\}\\(\\[.+?\\]\\):\\s *\\(.*?\\)\\s *\\( \"[^\"]*\"$\\|$\\)"
  438. "Regular expression for a link definition [id]: ...")
  439. (defconst markdown-regex-header-1-atx
  440. "^\\(# \\)\\(.*?\\)\\($\\| #+$\\)"
  441. "Regular expression for level 1 atx-style (hash mark) headers.")
  442. (defconst markdown-regex-header-2-atx
  443. "^\\(## \\)\\(.*?\\)\\($\\| #+$\\)"
  444. "Regular expression for level 2 atx-style (hash mark) headers.")
  445. (defconst markdown-regex-header-3-atx
  446. "^\\(### \\)\\(.*?\\)\\($\\| #+$\\)"
  447. "Regular expression for level 3 atx-style (hash mark) headers.")
  448. (defconst markdown-regex-header-4-atx
  449. "^\\(#### \\)\\(.*?\\)\\($\\| #+$\\)"
  450. "Regular expression for level 4 atx-style (hash mark) headers.")
  451. (defconst markdown-regex-header-5-atx
  452. "^\\(##### \\)\\(.*?\\)\\($\\| #+$\\)"
  453. "Regular expression for level 5 atx-style (hash mark) headers.")
  454. (defconst markdown-regex-header-6-atx
  455. "^\\(###### \\)\\(.*?\\)\\($\\| #+$\\)"
  456. "Regular expression for level 6 atx-style (hash mark) headers.")
  457. (defconst markdown-regex-header-1-setext
  458. "^\\(.*\\)\n\\(===+\\)$"
  459. "Regular expression for level 1 setext-style (underline) headers.")
  460. (defconst markdown-regex-header-2-setext
  461. "^\\(.*\\)\n\\(---+\\)$"
  462. "Regular expression for level 2 setext-style (underline) headers.")
  463. (defconst markdown-regex-hr
  464. "^\\(\\*[ ]?\\*[ ]?\\*[ ]?[\\* ]*\\|-[ ]?-[ ]?-[--- ]*\\)$"
  465. "Regular expression for matching Markdown horizontal rules.")
  466. (defconst markdown-regex-code
  467. "\\(^\\|[^\\]\\)\\(\\(`\\{1,2\\}\\)\\([^ \\]\\|[^ ].*?[^ \\]\\)\\3\\)"
  468. "Regular expression for matching inline code fragments.")
  469. (defconst markdown-regex-pre
  470. "^\\( \\|\t\\).*$"
  471. "Regular expression for matching preformatted text sections.")
  472. (defconst markdown-regex-list
  473. "^[ \t]*\\([0-9]+\\.\\|[\\*\\+-]\\) "
  474. "Regular expression for matching list markers.")
  475. (defconst markdown-regex-bold
  476. "\\(^\\|[^\\]\\)\\(\\([*_]\\{2\\}\\)\\(.\\|\n\\)*?[^\\ ]\\3\\)"
  477. "Regular expression for matching bold text.")
  478. (defconst markdown-regex-italic
  479. "\\(^\\|[^\\]\\)\\(\\([*_]\\)\\([^ \\]\\3\\|[^ ]\\(.\\|\n\\)*?[^\\ ]\\3\\)\\)"
  480. "Regular expression for matching italic text.")
  481. (defconst markdown-regex-blockquote
  482. "^>.*$"
  483. "Regular expression for matching blockquote lines.")
  484. (defconst markdown-regex-line-break
  485. " $"
  486. "Regular expression for matching line breaks.")
  487. (defconst markdown-regex-wiki-link
  488. "\\[\\[[^]]+\\]\\]"
  489. "Regular expression for matching wiki links.")
  490. (defconst markdown-regex-uri
  491. (concat
  492. "\\(" (mapconcat 'identity markdown-uri-types "\\|")
  493. "\\):[^]\t\n\r<>,;() ]+")
  494. "Regular expression for matching inline URIs.")
  495. (defconst markdown-regex-angle-uri
  496. (concat
  497. "\\(<\\)\\("
  498. (mapconcat 'identity markdown-uri-types "\\|")
  499. "\\):[^]\t\n\r<>,;()]+\\(>\\)")
  500. "Regular expression for matching inline URIs in angle brackets.")
  501. (defconst markdown-regex-email
  502. "<\\(\\sw\\|\\s_\\|\\s.\\)+@\\(\\sw\\|\\s_\\|\\s.\\)+>"
  503. "Regular expression for matching inline email addresses.")
  504. (defconst markdown-regex-latex-expression
  505. "\\(^\\|[^\\]\\)\\(\\$\\($\\([^\\$]\\|\\\\.\\)*\\$\\|\\([^\\$]\\|\\\\.\\)*\\)\\$\\)"
  506. "Regular expression for itex $..$ or $$..$$ math mode expressions.")
  507. (defconst markdown-regex-latex-display
  508. "^\\\\\\[\\(.\\|\n\\)*?\\\\\\]$"
  509. "Regular expression for itex \[..\] display mode expressions.")
  510. (defconst markdown-regex-list-indent
  511. "^\\(\\s *\\)\\([0-9]+\\.\\|[\\*\\+-]\\)\\(\\s +\\)"
  512. "Regular expression for matching indentation of list items.")
  513. ; From html-helper-mode
  514. (defun markdown-match-comments (last)
  515. "Matches HTML comments from the point to LAST"
  516. (cond ((search-forward "<!--" last t)
  517. (backward-char 4)
  518. (let ((beg (point)))
  519. (cond ((search-forward-regexp "--[ \t]*>" last t)
  520. (set-match-data (list beg (point)))
  521. t)
  522. (t nil))))
  523. (t nil)))
  524. (defvar markdown-mode-font-lock-keywords-basic
  525. (list
  526. '(markdown-match-comments 0 markdown-comment-face t t)
  527. (cons markdown-regex-code '(2 markdown-inline-code-face))
  528. (cons markdown-regex-pre 'markdown-pre-face)
  529. (cons markdown-regex-blockquote 'markdown-blockquote-face)
  530. (cons markdown-regex-header-1-setext 'markdown-header-face-1)
  531. (cons markdown-regex-header-2-setext 'markdown-header-face-2)
  532. (cons markdown-regex-header-1-atx 'markdown-header-face-1)
  533. (cons markdown-regex-header-2-atx 'markdown-header-face-2)
  534. (cons markdown-regex-header-3-atx 'markdown-header-face-3)
  535. (cons markdown-regex-header-4-atx 'markdown-header-face-4)
  536. (cons markdown-regex-header-5-atx 'markdown-header-face-5)
  537. (cons markdown-regex-header-6-atx 'markdown-header-face-6)
  538. (cons markdown-regex-hr 'markdown-header-face)
  539. (cons markdown-regex-list 'markdown-list-face)
  540. (cons markdown-regex-link-inline
  541. '((1 markdown-link-face t)
  542. (2 markdown-url-face t)))
  543. (cons markdown-regex-link-reference
  544. '((1 markdown-link-face t)
  545. (2 markdown-reference-face t)))
  546. (cons markdown-regex-reference-definition
  547. '((1 markdown-reference-face t)
  548. (2 markdown-url-face t)
  549. (3 markdown-link-title-face t)))
  550. (cons markdown-regex-wiki-link 'markdown-link-face)
  551. (cons markdown-regex-bold '(2 markdown-bold-face))
  552. (cons markdown-regex-italic '(2 markdown-italic-face))
  553. (cons markdown-regex-angle-uri 'markdown-link-face)
  554. (cons markdown-regex-uri 'markdown-link-face)
  555. (cons markdown-regex-email 'markdown-link-face)
  556. )
  557. "Syntax highlighting for Markdown files.")
  558. (defconst markdown-mode-font-lock-keywords-latex
  559. (list
  560. ;; Math mode $..$ or $$..$$
  561. (cons markdown-regex-latex-expression '(2 markdown-math-face))
  562. ;; Display mode equations with brackets: \[ \]
  563. (cons markdown-regex-latex-display 'markdown-math-face)
  564. ;; Equation reference (eq:foo)
  565. (cons "(eq:\\w+)" 'markdown-reference-face)
  566. ;; Equation reference \eqref{foo}
  567. (cons "\\\\eqref{\\w+}" 'markdown-reference-face))
  568. "Syntax highlighting for LaTeX fragments.")
  569. (defvar markdown-mode-font-lock-keywords
  570. (append
  571. (if markdown-enable-math
  572. markdown-mode-font-lock-keywords-latex)
  573. markdown-mode-font-lock-keywords-basic)
  574. "Default highlighting expressions for Markdown mode.")
  575. ;;; Syntax Table ==============================================================
  576. (defvar markdown-mode-syntax-table
  577. (let ((markdown-mode-syntax-table (make-syntax-table)))
  578. (modify-syntax-entry ?\" "w" markdown-mode-syntax-table)
  579. markdown-mode-syntax-table)
  580. "Syntax table for `markdown-mode'.")
  581. ;;; Element Insertion =========================================================
  582. (defun markdown-wrap-or-insert (s1 s2)
  583. "Insert the strings S1 and S2.
  584. If Transient Mark mode is on and a region is active, wrap the strings S1
  585. and S2 around the region."
  586. (if (and transient-mark-mode mark-active)
  587. (let ((a (region-beginning)) (b (region-end)))
  588. (goto-char a)
  589. (insert s1)
  590. (goto-char (+ b (length s1)))
  591. (insert s2))
  592. (insert s1 s2)))
  593. (defun markdown-insert-hr ()
  594. "Insert a horizonal rule."
  595. (interactive)
  596. (let (hr)
  597. (dotimes (count (- markdown-hr-length 1) hr) ; Count to n - 1
  598. (setq hr (concat "* " hr))) ; Build HR string
  599. (setq hr (concat hr "*\n")) ; Add the n-th *
  600. (insert hr)))
  601. (defun markdown-insert-bold ()
  602. "Insert markup for a bold word or phrase.
  603. If Transient Mark mode is on and a region is active, it is made bold."
  604. (interactive)
  605. (if markdown-bold-underscore
  606. (markdown-wrap-or-insert "__" "__")
  607. (markdown-wrap-or-insert "**" "**"))
  608. (backward-char 2))
  609. (defun markdown-insert-italic ()
  610. "Insert markup for an italic word or phrase.
  611. If Transient Mark mode is on and a region is active, it is made italic."
  612. (interactive)
  613. (if markdown-italic-underscore
  614. (markdown-wrap-or-insert "_" "_")
  615. (markdown-wrap-or-insert "*" "*"))
  616. (backward-char 1))
  617. (defun markdown-insert-code ()
  618. "Insert markup for an inline code fragment.
  619. If Transient Mark mode is on and a region is active, it is marked
  620. as inline code."
  621. (interactive)
  622. (markdown-wrap-or-insert "`" "`")
  623. (backward-char 1))
  624. (defun markdown-insert-link ()
  625. "Insert an inline link of the form []().
  626. If Transient Mark mode is on and a region is active, it is used
  627. as the link text."
  628. (interactive)
  629. (markdown-wrap-or-insert "[" "]")
  630. (insert "()")
  631. (backward-char 1))
  632. (defun markdown-insert-wiki-link ()
  633. "Insert a wiki link of the form [[WikiLink]].
  634. If Transient Mark mode is on and a region is active, it is used
  635. as the link text."
  636. (interactive)
  637. (markdown-wrap-or-insert "[[" "]]")
  638. (backward-char 2))
  639. (defun markdown-insert-image ()
  640. "Insert an inline image tag of the form ![]().
  641. If Transient Mark mode is on and a region is active, it is used
  642. as the alt text of the image."
  643. (interactive)
  644. (markdown-wrap-or-insert "![" "]")
  645. (insert "()")
  646. (backward-char 1))
  647. (defun markdown-insert-header-1 ()
  648. "Insert a first level atx-style (hash mark) header.
  649. If Transient Mark mode is on and a region is active, it is used
  650. as the header text."
  651. (interactive)
  652. (markdown-insert-header 1))
  653. (defun markdown-insert-header-2 ()
  654. "Insert a second level atx-style (hash mark) header.
  655. If Transient Mark mode is on and a region is active, it is used
  656. as the header text."
  657. (interactive)
  658. (markdown-insert-header 2))
  659. (defun markdown-insert-header-3 ()
  660. "Insert a third level atx-style (hash mark) header.
  661. If Transient Mark mode is on and a region is active, it is used
  662. as the header text."
  663. (interactive)
  664. (markdown-insert-header 3))
  665. (defun markdown-insert-header-4 ()
  666. "Insert a fourth level atx-style (hash mark) header.
  667. If Transient Mark mode is on and a region is active, it is used
  668. as the header text."
  669. (interactive)
  670. (markdown-insert-header 4))
  671. (defun markdown-insert-header-5 ()
  672. "Insert a fifth level atx-style (hash mark) header.
  673. If Transient Mark mode is on and a region is active, it is used
  674. as the header text."
  675. (interactive)
  676. (markdown-insert-header 5))
  677. (defun markdown-insert-header-6 ()
  678. "Insert a sixth level atx-style (hash mark) header.
  679. If Transient Mark mode is on and a region is active, it is used
  680. as the header text."
  681. (interactive)
  682. (markdown-insert-header 6))
  683. (defun markdown-insert-header (n)
  684. "Insert an atx-style (hash mark) header.
  685. With no prefix argument, insert a level-1 header. With prefix N,
  686. insert a level-N header. If Transient Mark mode is on and the
  687. region is active, it is used as the header text."
  688. (interactive "p")
  689. (unless n ; Test to see if n is defined
  690. (setq n 1)) ; Default to level 1 header
  691. (let (hdr hdrl hdrr)
  692. (dotimes (count n hdr)
  693. (setq hdr (concat "#" hdr))) ; Build a hash mark header string
  694. (setq hdrl (concat hdr " "))
  695. (setq hdrr (concat " " hdr))
  696. (markdown-wrap-or-insert hdrl hdrr))
  697. (backward-char (+ 1 n)))
  698. (defun markdown-insert-title ()
  699. "Insert a setext-style (underline) first level header.
  700. If Transient Mark mode is on and a region is active, it is used
  701. as the header text."
  702. (interactive)
  703. (if (and transient-mark-mode mark-active)
  704. (let ((a (region-beginning))
  705. (b (region-end))
  706. (len 0)
  707. (hdr))
  708. (setq len (- b a))
  709. (dotimes (count len hdr)
  710. (setq hdr (concat "=" hdr))) ; Build a === title underline
  711. (end-of-line)
  712. (insert "\n" hdr "\n"))
  713. (insert "\n==========\n")
  714. (backward-char 12)))
  715. (defun markdown-insert-section ()
  716. "Insert a setext-style (underline) second level header.
  717. If Transient Mark mode is on and a region is active, it is used
  718. as the header text."
  719. (interactive)
  720. (if (and transient-mark-mode mark-active)
  721. (let ((a (region-beginning))
  722. (b (region-end))
  723. (len 0)
  724. (hdr))
  725. (setq len (- b a))
  726. (dotimes (count len hdr)
  727. (setq hdr (concat "-" hdr))) ; Build a --- section underline
  728. (end-of-line)
  729. (insert "\n" hdr "\n"))
  730. (insert "\n----------\n")
  731. (backward-char 12)))
  732. (defun markdown-insert-blockquote ()
  733. "Start a blockquote section (or blockquote the region).
  734. If Transient Mark mode is on and a region is active, it is used as
  735. the blockquote text."
  736. (interactive)
  737. (if (and (boundp 'transient-mark-mode) transient-mark-mode mark-active)
  738. (markdown-blockquote-region (region-beginning) (region-end))
  739. (insert "> ")))
  740. (defun markdown-block-region (beg end prefix)
  741. "Format the region using a block prefix.
  742. Arguments BEG and END specify the beginning and end of the
  743. region.The characters PREFIX will appear at the beginning
  744. of each line."
  745. (if mark-active
  746. (save-excursion
  747. (let ((endpos end))
  748. ; Ensure that there is a leading blank line
  749. (goto-char beg)
  750. (while (not (looking-back "\n\n" 2))
  751. (insert "\n")
  752. (setq endpos (+ 1 endpos)))
  753. ; Insert blockquote characters
  754. (move-to-left-margin)
  755. (while (< (point-at-bol) endpos)
  756. (insert prefix)
  757. (setq endpos (+ (length prefix) endpos))
  758. (forward-line))
  759. ; Move back before any blank lines at the end
  760. (goto-char endpos)
  761. (while (looking-back "\n" 1)
  762. (backward-char))
  763. ; Ensure one blank line at the end
  764. (while (not (looking-at "\n\n"))
  765. (insert "\n")
  766. (backward-char))))))
  767. (defun markdown-blockquote-region (beg end)
  768. "Blockquote the region.
  769. Arguments BEG and END specify the beginning and end of the region."
  770. (interactive "*r")
  771. (markdown-block-region beg end "> "))
  772. (defun markdown-insert-pre ()
  773. "Start a preformatted section (or apply to the region).
  774. If Transient Mark mode is on and a region is active, it is marked
  775. as preformatted text."
  776. (interactive)
  777. (if (and (boundp 'transient-mark-mode) transient-mark-mode mark-active)
  778. (markdown-pre-region (region-beginning) (region-end))
  779. (insert " ")))
  780. (defun markdown-pre-region (beg end)
  781. "Format the region as preformatted text.
  782. Arguments BEG and END specify the beginning and end of the region."
  783. (interactive "*r")
  784. (markdown-block-region beg end " "))
  785. ;;; Indentation ====================================================================
  786. ;;; Indentation functions contributed by Bryan Kyle <bryan.kyle@gmail.com>..
  787. (defun markdown-indent-find-next-position (cur-pos positions)
  788. "Return the position after the index of CUR-POS in POSITIONS."
  789. (while (and positions
  790. (not (equal cur-pos (car positions))))
  791. (setq positions (cdr positions)))
  792. (or (cadr positions) 0))
  793. (defun markdown-prev-line-indent-p ()
  794. "Return t if the previous line is indented."
  795. (save-excursion
  796. (forward-line -1)
  797. (goto-char (point-at-bol))
  798. (if (re-search-forward "^\\s " (point-at-eol) t) t)))
  799. (defun markdown-prev-line-indent ()
  800. "Return the number of leading whitespace characters in the previous line."
  801. (save-excursion
  802. (forward-line -1)
  803. (goto-char (point-at-bol))
  804. (when (re-search-forward "^\\s +" (point-at-eol) t)
  805. (current-column))))
  806. (defun markdown-prev-list-indent ()
  807. "Return position of the first non-list-marker on the previous line."
  808. (save-excursion
  809. (forward-line -1)
  810. (goto-char (point-at-bol))
  811. (when (re-search-forward markdown-regex-list-indent (point-at-eol) t)
  812. (current-column))))
  813. (defun markdown-indent-line ()
  814. "Indent the current line using some heuristics."
  815. (interactive)
  816. (if (markdown-prev-line-indent-p)
  817. ;; If the current column is any of the positions, remove all
  818. ;; of the positions up-to and including the current column
  819. (indent-line-to
  820. (markdown-indent-find-next-position
  821. (current-column) (markdown-calc-indents)))))
  822. (defun markdown-calc-indents ()
  823. "Return a list of indentation columns to cycle through."
  824. (let (pos
  825. prev-line-pos
  826. positions
  827. computed-pos)
  828. ;; Previous line indent
  829. (setq prev-line-pos (markdown-prev-line-indent))
  830. (setq positions (cons prev-line-pos positions))
  831. ;; Previous non-list-marker indent
  832. (setq positions (cons (markdown-prev-list-indent) positions))
  833. ;; Indentation of the previous line + tab-width
  834. (cond
  835. (prev-line-pos
  836. (setq positions (cons (+ prev-line-pos tab-width) positions)))
  837. (t
  838. (setq positions (cons tab-width positions))))
  839. ;; Indentation of the previous line - tab-width
  840. (if (and prev-line-pos
  841. (> prev-line-pos tab-width))
  842. (setq positions (cons (- prev-line-pos tab-width) positions)))
  843. ;; Indentation of preceeding list item
  844. (setq pos
  845. (save-excursion
  846. (forward-line -1)
  847. (catch 'break
  848. (while (not (equal (point) (point-min)))
  849. (forward-line -1)
  850. (goto-char (point-at-bol))
  851. (when (re-search-forward markdown-regex-list-indent (point-at-eol) t)
  852. (throw 'break (length (match-string 1)))))
  853. nil)))
  854. (if pos
  855. (setq positions (cons pos positions)))
  856. ;; First column
  857. (setq positions (cons 0 (reverse positions)))
  858. positions))
  859. (defun markdown-enter-key ()
  860. "Insert a newline and optionally indent the next line."
  861. (interactive)
  862. (newline)
  863. (if markdown-indent-on-enter
  864. (funcall indent-line-function)))
  865. ;;; Keymap ====================================================================
  866. (defvar markdown-mode-map
  867. (let ((markdown-mode-map (make-keymap)))
  868. ;; Element insertion
  869. (define-key markdown-mode-map "\C-c\C-al" 'markdown-insert-link)
  870. (define-key markdown-mode-map "\C-c\C-aw" 'markdown-insert-wiki-link)
  871. (define-key markdown-mode-map "\C-c\C-ii" 'markdown-insert-image)
  872. (define-key markdown-mode-map "\C-c\C-t1" 'markdown-insert-header-1)
  873. (define-key markdown-mode-map "\C-c\C-t2" 'markdown-insert-header-2)
  874. (define-key markdown-mode-map "\C-c\C-t3" 'markdown-insert-header-3)
  875. (define-key markdown-mode-map "\C-c\C-t4" 'markdown-insert-header-4)
  876. (define-key markdown-mode-map "\C-c\C-t5" 'markdown-insert-header-5)
  877. (define-key markdown-mode-map "\C-c\C-t6" 'markdown-insert-header-6)
  878. (define-key markdown-mode-map "\C-c\C-pb" 'markdown-insert-bold)
  879. (define-key markdown-mode-map "\C-c\C-ss" 'markdown-insert-bold)
  880. (define-key markdown-mode-map "\C-c\C-pi" 'markdown-insert-italic)
  881. (define-key markdown-mode-map "\C-c\C-se" 'markdown-insert-italic)
  882. (define-key markdown-mode-map "\C-c\C-pf" 'markdown-insert-code)
  883. (define-key markdown-mode-map "\C-c\C-sc" 'markdown-insert-code)
  884. (define-key markdown-mode-map "\C-c\C-sb" 'markdown-insert-blockquote)
  885. (define-key markdown-mode-map "\C-c\C-s\C-b" 'markdown-blockquote-region)
  886. (define-key markdown-mode-map "\C-c\C-sp" 'markdown-insert-pre)
  887. (define-key markdown-mode-map "\C-c\C-s\C-p" 'markdown-pre-region)
  888. (define-key markdown-mode-map "\C-c-" 'markdown-insert-hr)
  889. (define-key markdown-mode-map "\C-c\C-tt" 'markdown-insert-title)
  890. (define-key markdown-mode-map "\C-c\C-ts" 'markdown-insert-section)
  891. ;; Indentation
  892. (define-key markdown-mode-map "\C-m" 'markdown-enter-key)
  893. ;; Visibility cycling
  894. (define-key markdown-mode-map (kbd "<tab>") 'markdown-cycle)
  895. (define-key markdown-mode-map (kbd "<S-iso-lefttab>") 'markdown-shifttab)
  896. ;; Markdown functions
  897. (define-key markdown-mode-map "\C-c\C-cm" 'markdown)
  898. (define-key markdown-mode-map "\C-c\C-cp" 'markdown-preview)
  899. ;; References
  900. (define-key markdown-mode-map "\C-c\C-cc" 'markdown-check-refs)
  901. markdown-mode-map)
  902. "Keymap for Markdown major mode.")
  903. ;;; Menu ==================================================================
  904. (easy-menu-define markdown-mode-menu markdown-mode-map
  905. "Menu for Markdown mode"
  906. '("Markdown"
  907. ("Show/Hide"
  908. ["Cycle visibility" markdown-cycle (outline-on-heading-p)]
  909. ["Cycle global visibility" markdown-shifttab])
  910. "---"
  911. ["Compile" markdown]
  912. ["Preview" markdown-preview]
  913. "---"
  914. ("Headers (setext)"
  915. ["Insert Title" markdown-insert-title]
  916. ["Insert Section" markdown-insert-section])
  917. ("Headers (atx)"
  918. ["First level" markdown-insert-header-1]
  919. ["Second level" markdown-insert-header-2]
  920. ["Third level" markdown-insert-header-3]
  921. ["Fourth level" markdown-insert-header-4]
  922. ["Fifth level" markdown-insert-header-5]
  923. ["Sixth level" markdown-insert-header-6])
  924. "---"
  925. ["Bold" markdown-insert-bold]
  926. ["Italic" markdown-insert-italic]
  927. ["Blockquote" markdown-insert-blockquote]
  928. ["Preformatted" markdown-insert-pre]
  929. ["Code" markdown-insert-code]
  930. "---"
  931. ["Insert inline link" markdown-insert-link]
  932. ["Insert image" markdown-insert-image]
  933. ["Insert horizontal rule" markdown-insert-hr]
  934. "---"
  935. ["Check references" markdown-check-refs]
  936. "---"
  937. ["Version" markdown-show-version]
  938. ))
  939. ;;; References ================================================================
  940. ;;; Undefined reference checking code by Dmitry Dzhus <mail@sphinx.net.ru>.
  941. (defconst markdown-refcheck-buffer
  942. "*Undefined references for %BUFFER%*"
  943. "Pattern for name of buffer for listing undefined references.
  944. The string %BUFFER% will be replaced by the corresponding
  945. `markdown-mode' buffer name.")
  946. (defun markdown-has-reference-definition (reference)
  947. "Find out whether Markdown REFERENCE is defined.
  948. REFERENCE should include the square brackets, like [this]."
  949. (let ((reference (downcase reference)))
  950. (save-excursion
  951. (goto-char (point-min))
  952. (catch 'found
  953. (while (re-search-forward markdown-regex-reference-definition nil t)
  954. (when (string= reference (downcase (match-string-no-properties 1)))
  955. (throw 'found t)))))))
  956. (defun markdown-get-undefined-refs ()
  957. "Return a list of undefined Markdown references.
  958. Result is an alist of pairs (reference . occurencies), where
  959. occurencies is itself another alist of pairs (label .
  960. line-number).
  961. For example, an alist corresponding to [Nice editor][Emacs] at line 12,
  962. \[GNU Emacs][Emacs] at line 45 and [manual][elisp] at line 127 is
  963. \((\"[emacs]\" (\"[Nice editor]\" . 12) (\"[GNU Emacs]\" . 45)) (\"[elisp]\" (\"[manual]\" . 127)))."
  964. (let ((missing))
  965. (save-excursion
  966. (goto-char (point-min))
  967. (while
  968. (re-search-forward markdown-regex-link-reference nil t)
  969. (let* ((label (match-string-no-properties 1))
  970. (reference (match-string-no-properties 2))
  971. (target (downcase (if (string= reference "[]") label reference))))
  972. (unless (markdown-has-reference-definition target)
  973. (let ((entry (assoc target missing)))
  974. (if (not entry)
  975. (add-to-list 'missing (cons target
  976. (list (cons label (markdown-line-number-at-pos)))) t)
  977. (setcdr entry
  978. (append (cdr entry) (list (cons label (markdown-line-number-at-pos))))))))))
  979. missing)))
  980. (defun markdown-add-missing-ref-definition (ref buffer &optional recheck)
  981. "Add blank REF definition to the end of BUFFER.
  982. REF is a Markdown reference in square brackets, like \"[lisp-history]\".
  983. When RECHECK is non-nil, BUFFER gets rechecked for undefined
  984. references so that REF disappears from the list of those links."
  985. (with-current-buffer buffer
  986. (when (not (eq major-mode 'markdown-mode))
  987. (error "Not available in current mode"))
  988. (goto-char (point-max))
  989. (indent-new-comment-line)
  990. (insert (concat ref ": ")))
  991. (switch-to-buffer-other-window buffer)
  992. (goto-char (point-max))
  993. (when recheck
  994. (markdown-check-refs t)))
  995. ;; Button which adds an empty Markdown reference definition to the end
  996. ;; of buffer specified as its 'target-buffer property. Reference name
  997. ;; is button's label
  998. (when (>= emacs-major-version 22)
  999. (define-button-type 'markdown-ref-button
  1000. 'help-echo "Push to create an empty reference definition"
  1001. 'face 'bold
  1002. 'action (lambda (b)
  1003. (markdown-add-missing-ref-definition
  1004. (button-label b) (button-get b 'target-buffer) t))))
  1005. ;; Button jumping to line in buffer specified as its 'target-buffer
  1006. ;; property. Line number is button's 'line property.
  1007. (when (>= emacs-major-version 22)
  1008. (define-button-type 'goto-line-button
  1009. 'help-echo "Push to go to this line"
  1010. 'face 'italic
  1011. 'action (lambda (b)
  1012. (message (button-get b 'buffer))
  1013. (switch-to-buffer-other-window (button-get b 'target-buffer))
  1014. (goto-line (button-get b 'target-line)))))
  1015. (defun markdown-check-refs (&optional silent)
  1016. "Show all undefined Markdown references in current `markdown-mode' buffer.
  1017. If SILENT is non-nil, do not message anything when no undefined
  1018. references found.
  1019. Links which have empty reference definitions are considered to be
  1020. defined."
  1021. (interactive "P")
  1022. (when (not (eq major-mode 'markdown-mode))
  1023. (error "Not available in current mode"))
  1024. (let ((oldbuf (current-buffer))
  1025. (refs (markdown-get-undefined-refs))
  1026. (refbuf (get-buffer-create (replace-regexp-in-string
  1027. "%BUFFER%" (buffer-name)
  1028. markdown-refcheck-buffer t))))
  1029. (if (null refs)
  1030. (progn
  1031. (when (not silent)
  1032. (message "No undefined references found"))
  1033. (kill-buffer refbuf))
  1034. (with-current-buffer refbuf
  1035. (when view-mode
  1036. (View-exit-and-edit))
  1037. (erase-buffer)
  1038. (insert "Following references lack definitions:")
  1039. (newline 2)
  1040. (dolist (ref refs)
  1041. (let ((button-label (format "%s" (car ref))))
  1042. (if (>= emacs-major-version 22)
  1043. ;; Create a reference button in Emacs 22
  1044. (insert-text-button button-label
  1045. :type 'markdown-ref-button
  1046. 'target-buffer oldbuf)
  1047. ;; Insert reference as text in Emacs < 22
  1048. (insert button-label)))
  1049. (insert " (")
  1050. (dolist (occurency (cdr ref))
  1051. (let ((line (cdr occurency)))
  1052. (if (>= emacs-major-version 22)
  1053. ;; Create a line number button in Emacs 22
  1054. (insert-button (number-to-string line)
  1055. :type 'goto-line-button
  1056. 'target-buffer oldbuf
  1057. 'target-line line)
  1058. ;; Insert line number as text in Emacs < 22
  1059. (insert (number-to-string line)))
  1060. (insert " "))) (delete-backward-char 1)
  1061. (insert ")")
  1062. (newline))
  1063. (view-buffer-other-window refbuf)
  1064. (goto-line 4)))))
  1065. ;;; Outline ===================================================================
  1066. ;; The following visibility cycling code was taken from org-mode
  1067. ;; by Carsten Dominik and adapted for markdown-mode.
  1068. (defvar markdown-cycle-global-status 1)
  1069. (defvar markdown-cycle-subtree-status nil)
  1070. ;; Based on org-end-of-subtree from org.el
  1071. (defun markdown-end-of-subtree (&optional invisible-OK)
  1072. "Move to the end of the current subtree.
  1073. Only visible heading lines are considered, unless INVISIBLE-OK is
  1074. non-nil."
  1075. (outline-back-to-heading invisible-OK)
  1076. (let ((first t)
  1077. (level (funcall outline-level)))
  1078. (while (and (not (eobp))
  1079. (or first (> (funcall outline-level) level)))
  1080. (setq first nil)
  1081. (outline-next-heading))
  1082. (if (memq (preceding-char) '(?\n ?\^M))
  1083. (progn
  1084. ;; Go to end of line before heading
  1085. (forward-char -1)
  1086. (if (memq (preceding-char) '(?\n ?\^M))
  1087. ;; leave blank line before heading
  1088. (forward-char -1)))))
  1089. (point))
  1090. ;; Based on org-cycle from org.el.
  1091. (defun markdown-cycle (&optional arg)
  1092. "Visibility cycling for Markdown mode.
  1093. If ARG is t, perform global visibility cycling. If the point is
  1094. at an atx-style header, cycle visibility of the corresponding
  1095. subtree. Otherwise, insert a tab using `indent-relative'."
  1096. (interactive "P")
  1097. (cond
  1098. ((eq arg t) ;; Global cycling
  1099. (cond
  1100. ((and (eq last-command this-command)
  1101. (eq markdown-cycle-global-status 2))
  1102. ;; Move from overview to contents
  1103. (hide-sublevels 1)
  1104. (message "CONTENTS")
  1105. (setq markdown-cycle-global-status 3))
  1106. ((and (eq last-command this-command)
  1107. (eq markdown-cycle-global-status 3))
  1108. ;; Move from contents to all
  1109. (show-all)
  1110. (message "SHOW ALL")
  1111. (setq markdown-cycle-global-status 1))
  1112. (t
  1113. ;; Defaults to overview
  1114. (hide-body)
  1115. (message "OVERVIEW")
  1116. (setq markdown-cycle-global-status 2))))
  1117. ((save-excursion (beginning-of-line 1) (looking-at outline-regexp))
  1118. ;; At a heading: rotate between three different views
  1119. (outline-back-to-heading)
  1120. (let ((goal-column 0) eoh eol eos)
  1121. ;; Determine boundaries
  1122. (save-excursion
  1123. (outline-back-to-heading)
  1124. (save-excursion
  1125. (beginning-of-line 2)
  1126. (while (and (not (eobp)) ;; this is like `next-line'
  1127. (get-char-property (1- (point)) 'invisible))
  1128. (beginning-of-line 2)) (setq eol (point)))
  1129. (outline-end-of-heading) (setq eoh (point))
  1130. (markdown-end-of-subtree t)
  1131. (skip-chars-forward " \t\n")
  1132. (beginning-of-line 1) ; in case this is an item
  1133. (setq eos (1- (point))))
  1134. ;; Find out what to do next and set `this-command'
  1135. (cond
  1136. ((= eos eoh)
  1137. ;; Nothing is hidden behind this heading
  1138. (message "EMPTY ENTRY")
  1139. (setq markdown-cycle-subtree-status nil))
  1140. ((>= eol eos)
  1141. ;; Entire subtree is hidden in one line: open it
  1142. (show-entry)
  1143. (show-children)
  1144. (message "CHILDREN")
  1145. (setq markdown-cycle-subtree-status 'children))
  1146. ((and (eq last-command this-command)
  1147. (eq markdown-cycle-subtree-status 'children))
  1148. ;; We just showed the children, now show everything.
  1149. (show-subtree)
  1150. (message "SUBTREE")
  1151. (setq markdown-cycle-subtree-status 'subtree))
  1152. (t
  1153. ;; Default action: hide the subtree.
  1154. (hide-subtree)
  1155. (message "FOLDED")
  1156. (setq markdown-cycle-subtree-status 'folded)))))
  1157. (t
  1158. (message "TAB")
  1159. (funcall indent-line-function))))
  1160. ;; Based on org-shifttab from org.el.
  1161. (defun markdown-shifttab ()
  1162. "Global visibility cycling.
  1163. Calls `markdown-cycle' with argument t."
  1164. (interactive)
  1165. (markdown-cycle t))
  1166. ;;; Commands ==================================================================
  1167. (defun markdown ()
  1168. "Run markdown on the current buffer and preview the output in another buffer."
  1169. (interactive)
  1170. (if (and (boundp 'transient-mark-mode) transient-mark-mode mark-active)
  1171. (shell-command-on-region (region-beginning) (region-end) markdown-command
  1172. "*markdown-output*" nil)
  1173. (shell-command-on-region (point-min) (point-max) markdown-command
  1174. "*markdown-output*" nil))
  1175. (let (title)
  1176. (setq title (buffer-name))
  1177. (save-excursion
  1178. (set-buffer "*markdown-output*")
  1179. (goto-char (point-min))
  1180. (insert "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"
  1181. "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"\n"
  1182. "\t\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n\n"
  1183. "<html xmlns=\"http://www.w3.org/1999/xhtml\">\n\n"
  1184. "<head>\n<title>")
  1185. (insert title)
  1186. (insert "</title>\n")
  1187. (if markdown-css-path
  1188. (insert "<link rel=\"stylesheet\" type=\"text/css\" media=\"all\" href=\""
  1189. markdown-css-path
  1190. "\" />\n"))
  1191. (insert "</head>\n\n"
  1192. "<body>\n\n")
  1193. (goto-char (point-max))
  1194. (insert "\n"
  1195. "</body>\n"
  1196. "</html>\n"))))
  1197. (defun markdown-preview ()
  1198. "Run markdown on the current buffer and preview the output in a browser."
  1199. (interactive)
  1200. (markdown)
  1201. (browse-url-of-buffer "*markdown-output*"))
  1202. ;;; Miscellaneous =============================================================
  1203. (defun markdown-line-number-at-pos (&optional pos)
  1204. "Return (narrowed) buffer line number at position POS.
  1205. If POS is nil, use current buffer location.
  1206. This is an exact copy of `line-number-at-pos' for use in emacs21."
  1207. (let ((opoint (or pos (point))) start)
  1208. (save-excursion
  1209. (goto-char (point-min))
  1210. (setq start (point))
  1211. (goto-char opoint)
  1212. (forward-line 0)
  1213. (1+ (count-lines start (point))))))
  1214. (defun markdown-nobreak-p ()
  1215. "Returns nil if it is ok for fill-paragraph to insert a line
  1216. break at point"
  1217. ;; are we inside in square brackets
  1218. (looking-back "\\[[^]]*"))
  1219. ;;; Mode definition ==========================================================
  1220. (defun markdown-show-version ()
  1221. "Show the version number in the minibuffer."
  1222. (interactive)
  1223. (message "markdown-mode, version %s" markdown-mode-version))
  1224. (define-derived-mode markdown-mode text-mode "Markdown"
  1225. "Major mode for editing Markdown files."
  1226. ;; Comments
  1227. (make-local-variable 'comment-start)
  1228. (setq comment-start "<!-- ")
  1229. (make-local-variable 'comment-end)
  1230. (setq comment-end " -->")
  1231. (make-local-variable 'comment-start-skip)
  1232. (setq comment-start-skip "<!--[ \t]*")
  1233. (make-local-variable 'comment-column)
  1234. (setq comment-column 0)
  1235. ;; Font lock.
  1236. (set (make-local-variable 'font-lock-defaults)
  1237. '(markdown-mode-font-lock-keywords))
  1238. (set (make-local-variable 'font-lock-multiline) t)
  1239. ;; For menu support in XEmacs
  1240. (easy-menu-add markdown-mode-menu markdown-mode-map)
  1241. ;; Make filling work with lists (unordered, ordered, and definition)
  1242. (set (make-local-variable 'paragraph-start)
  1243. "\f\\|[ \t]*$\\|^[ \t]*[*+-] \\|^[ \t*][0-9]+\\.\\|^[ \t]*: ")
  1244. ;; Outline mode
  1245. (make-local-variable 'outline-regexp)
  1246. (setq outline-regexp "#+")
  1247. ;; Cause use of ellipses for invisible text.
  1248. (add-to-invisibility-spec '(outline . t))
  1249. ;; Indentation and filling
  1250. (make-local-variable 'fill-nobreak-predicate)
  1251. (add-hook 'fill-nobreak-predicate 'markdown-nobreak-p)
  1252. (setq indent-line-function markdown-indent-function))
  1253. ;(add-to-list 'auto-mode-alist '("\\.text$" . markdown-mode))
  1254. (provide 'markdown-mode)
  1255. ;;; markdown-mode.el ends here