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