rst.el 142 KB
Newer Older
Stefan Monnier's avatar
Stefan Monnier committed
1 2
;;; rst.el --- Mode for viewing and editing reStructuredText-documents.

3
;; Copyright (C) 2003-2012  Free Software Foundation, Inc.
Stefan Monnier's avatar
Stefan Monnier committed
4

5
;; Maintainer: Stefan Merten <smerten@oekonux.de>
6 7
;; Author: Stefan Merten <smerten@oekonux.de>,
;;         Martin Blais <blais@furius.ca>,
8 9
;;         David Goodger <goodger@python.org>,
;;         Wei-Wei Guo <wwguocn@gmail.com>
Stefan Monnier's avatar
Stefan Monnier committed
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27

;; This file is part of GNU Emacs.

;; GNU Emacs is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.

;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;; GNU General Public License for more details.

;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.

;;; Commentary:

28
;; This package provides major mode rst-mode, which supports documents marked
29 30 31 32
;; up using the reStructuredText format.  Support includes font locking as well
;; as a lot of convenience functions for editing.  It does this by defining a
;; Emacs major mode: rst-mode (ReST).  This mode is derived from text-mode.
;; This package also contains:
Stefan Monnier's avatar
Stefan Monnier committed
33 34
;;
;; - Functions to automatically adjust and cycle the section underline
35
;;   adornments;
Stefan Monnier's avatar
Stefan Monnier committed
36 37 38 39
;; - A mode that displays the table of contents and allows you to jump anywhere
;;   from it;
;; - Functions to insert and automatically update a TOC in your source
;;   document;
40 41 42 43 44
;; - Function to insert list, processing item bullets and enumerations
;;   automatically;
;; - Font-lock highlighting of most reStructuredText structures;
;; - Indentation and filling according to reStructuredText syntax;
;; - Cursor movement according to reStructuredText syntax;
Stefan Monnier's avatar
Stefan Monnier committed
45 46 47 48 49 50 51 52 53 54 55 56
;; - Some other convenience functions.
;;
;; See the accompanying document in the docutils documentation about
;; the contents of this package and how to use it.
;;
;; For more information about reStructuredText, see
;; http://docutils.sourceforge.net/rst.html
;;
;; For full details on how to use the contents of this file, see
;; http://docutils.sourceforge.net/docs/user/emacs.html
;;
;;
57
;; There are a number of convenient key bindings provided by rst-mode.
Stefan Monnier's avatar
Stefan Monnier committed
58
;; For more on bindings, see rst-mode-map below.  There are also many variables
59
;; that can be customized, look for defcustom in this file.
Stefan Monnier's avatar
Stefan Monnier committed
60 61
;;
;; If you use the table-of-contents feature, you may want to add a hook to
62
;; update the TOC automatically every time you adjust a section title::
Stefan Monnier's avatar
Stefan Monnier committed
63 64 65
;;
;;   (add-hook 'rst-adjust-hook 'rst-toc-update)
;;
Stefan Monnier's avatar
Stefan Monnier committed
66 67
;; Syntax highlighting: font-lock is enabled by default.  If you want to turn
;; off syntax highlighting to rst-mode, you can use the following::
Stefan Monnier's avatar
Stefan Monnier committed
68 69 70 71 72
;;
;;   (setq font-lock-global-modes '(not rst-mode ...))
;;
;;
;;
73
;; Customization is done by customizable variables contained in customization
74
;; group "rst" and subgroups.  Group "rst" is contained in the "wp" group.
Stefan Monnier's avatar
Stefan Monnier committed
75 76 77 78
;;

;;; DOWNLOAD

79 80
;; The latest release of this file lies in the docutils source code repository:
;;   http://docutils.svn.sourceforge.net/svnroot/docutils/trunk/docutils/tools/editors/emacs/rst.el
Stefan Monnier's avatar
Stefan Monnier committed
81 82 83 84 85 86 87 88 89 90

;;; INSTALLATION

;; Add the following lines to your `.emacs' file:
;;
;;   (require 'rst)
;;
;; If you are using `.txt' as a standard extension for reST files as
;; http://docutils.sourceforge.net/FAQ.html#what-s-the-standard-filename-extension-for-a-restructuredtext-file
;; suggests you may use one of the `Local Variables in Files' mechanism Emacs
Stefan Monnier's avatar
Stefan Monnier committed
91
;; provides to set the major mode automatically.  For instance you may use::
Stefan Monnier's avatar
Stefan Monnier committed
92 93 94
;;
;;    .. -*- mode: rst -*-
;;
Stefan Monnier's avatar
Stefan Monnier committed
95 96
;; in the very first line of your file.  The following code is useful if you
;; want automatically enter rst-mode from any file with compatible extensions:
Stefan Monnier's avatar
Stefan Monnier committed
97 98
;;
;; (setq auto-mode-alist
99 100 101
;;       (append '(("\\.txt\\'" . rst-mode)
;;                 ("\\.rst\\'" . rst-mode)
;;                 ("\\.rest\\'" . rst-mode)) auto-mode-alist))
Stefan Monnier's avatar
Stefan Monnier committed
102 103
;;

104
;;; Code:
Stefan Monnier's avatar
Stefan Monnier committed
105

Stefan Merten's avatar
Stefan Merten committed
106 107 108
;; FIXME: Use `eval-when-compile' when calls to `some', `position', `signum'
;;        and `position-if' are replaced.
(require 'cl)
Stefan Monnier's avatar
Stefan Monnier committed
109

110 111 112 113
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Versions

(defun rst-extract-version (delim-re head-re re tail-re var &optional default)
114 115 116
  "Extract the version from a variable according to the given regexes.
Return the version after regex DELIM-RE and HEAD-RE matching RE
and before TAIL-RE and DELIM-RE in VAR or DEFAULT for no match."
117 118 119 120 121 122 123
  (if (string-match
       (concat delim-re head-re "\\(" re "\\)" tail-re delim-re)
       var)
      (match-string 1 var)
    default))

;; Use CVSHeader to really get information from CVS and not other version
124
;; control systems.
125
(defconst rst-cvs-header
126
  "$CVSHeader: sm/rst_el/rst.el,v 1.257.2.11 2012-06-02 12:20:41 stefan Exp $")
127 128 129
(defconst rst-cvs-rev
  (rst-extract-version "\\$" "CVSHeader: \\S + " "[0-9]+\\(?:\\.[0-9]+\\)+"
		       " .*" rst-cvs-header "0.0")
130
  "The CVS revision of this file.  CVS revision is the development revision.")
131 132 133 134
(defconst rst-cvs-timestamp
  (rst-extract-version "\\$" "CVSHeader: \\S + \\S + "
		       "[0-9]+-[0-9]+-[0-9]+ [0-9]+:[0-9]+:[0-9]+" " .*"
		       rst-cvs-header "1970-01-01 00:00:00")
135
  "The CVS time stamp of this file.")
136

137
;; Use LastChanged... to really get information from SVN.
138 139 140 141 142 143 144 145
(defconst rst-svn-rev
  (rst-extract-version "\\$" "LastChangedRevision: " "[0-9]+" " "
		       "$LastChangedRevision: 7399 $")
  "The SVN revision of this file.
SVN revision is the upstream (docutils) revision.")
(defconst rst-svn-timestamp
  (rst-extract-version "\\$" "LastChangedDate: " ".+?+" " "
		       "$LastChangedDate: 2012-04-29 17:01:05 +0200 (Sun, 29 Apr 2012) $")
146
  "The SVN time stamp of this file.")
147

148
;; Maintained by the release process.
149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
(defconst rst-official-version
  (rst-extract-version "%" "OfficialVersion: " "[0-9]+\\(?:\\.[0-9]+\\)+" " "
		       "%OfficialVersion: 1.2.1 %")
  "Official version of the package.")
(defconst rst-official-cvs-rev
  (rst-extract-version "[%$]" "Revision: " "[0-9]+\\(?:\\.[0-9]+\\)+" " "
		       "%Revision: 1.256 %")
  "CVS revision of this file in the official version.")

(defconst rst-version
  (if (equal rst-official-cvs-rev rst-cvs-rev)
      rst-official-version
    (format "%s (development %s [%s])" rst-official-version
	    rst-cvs-rev rst-cvs-timestamp))
  "The version string.
164 165
Starts with the current official version.  For developer versions
in parentheses follows the development revision and the time stamp.")
166 167 168 169 170 171 172 173 174 175 176 177 178

(defconst rst-package-emacs-version-alist
  '(("1.0.0" . "24.0")
    ("1.1.0" . "24.0")
    ("1.2.0" . "24.0")
    ("1.2.1" . "24.0")))

(unless (assoc rst-official-version rst-package-emacs-version-alist)
  (error "Version %s not listed in `rst-package-emacs-version-alist'"
	 rst-version))

(add-to-list 'customize-package-emacs-version-alist
	     (cons 'ReST rst-package-emacs-version-alist))
Stefan Monnier's avatar
Stefan Monnier committed
179

180 181
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Initialize customization
Stefan Monnier's avatar
Stefan Monnier committed
182 183


Juanma Barranquero's avatar
Juanma Barranquero committed
184
(defgroup rst nil "Support for reStructuredText documents."
Stefan Monnier's avatar
Stefan Monnier committed
185 186 187 188 189 190
  :group 'wp
  :version "23.1"
  :link '(url-link "http://docutils.sourceforge.net/rst.html"))


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
191 192 193
;; Facilities for regular expressions used everywhere

;; The trailing numbers in the names give the number of referenceable regex
194
;; groups contained in the regex.
195 196

;; Used to be customizable but really is not customizable but fixed by the reST
197
;; syntax.
198
(defconst rst-bullets
199
  ;; Sorted so they can form a character class when concatenated.
200 201 202 203 204 205 206 207 208 209
  '(?- ?* ?+ ?\u2022 ?\u2023 ?\u2043)
  "List of all possible bullet characters for bulleted lists.")

(defconst rst-uri-schemes
  '("acap" "cid" "data" "dav" "fax" "file" "ftp" "gopher" "http" "https" "imap"
    "ldap" "mailto" "mid" "modem" "news" "nfs" "nntp" "pop" "prospero" "rtsp"
    "service" "sip" "tel" "telnet" "tip" "urn" "vemmi" "wais")
  "Supported URI schemes.")

(defconst rst-adornment-chars
210
  ;; Sorted so they can form a character class when concatenated.
211 212 213 214 215 216 217 218 219 220 221
  '(?\]
    ?! ?\" ?# ?$ ?% ?& ?' ?\( ?\) ?* ?+ ?, ?. ?/ ?: ?\; ?< ?= ?> ?? ?@ ?\[ ?\\
    ?^ ?_ ?` ?{ ?| ?} ?~
    ?-)
  "Characters which may be used in adornments for sections and transitions.")

(defconst rst-max-inline-length
  1000
  "Maximum length of inline markup to recognize.")

(defconst rst-re-alist-def
222 223 224 225 226 227 228 229
  ;; `*-beg' matches * at the beginning of a line.
  ;; `*-end' matches * at the end of a line.
  ;; `*-prt' matches a part of *.
  ;; `*-tag' matches *.
  ;; `*-sta' matches the start of * which may be followed by respective content.
  ;; `*-pfx' matches the delimiter left of *.
  ;; `*-sfx' matches the delimiter right of *.
  ;; `*-hlp' helper for *.
230 231 232 233 234 235
  ;;
  ;; A trailing number says how many referenceable groups are contained.
  `(

    ;; Horizontal white space (`hws')
    (hws-prt "[\t ]")
236 237
    (hws-tag hws-prt "*") ; Optional sequence of horizontal white space.
    (hws-sta hws-prt "+") ; Mandatory sequence of horizontal white space.
238 239

    ;; Lines (`lin')
240 241 242
    (lin-beg "^" hws-tag) ; Beginning of a possibly indented line.
    (lin-end hws-tag "$") ; End of a line with optional trailing white space.
    (linemp-tag "^" hws-tag "$") ; Empty line with optional white space.
243 244 245

    ;; Various tags and parts
    (ell-tag "\\.\\.\\.") ; Ellipsis
246 247 248 249 250 251 252 253
    (bul-tag ,(concat "[" rst-bullets "]")) ; A bullet.
    (ltr-tag "[a-zA-Z]") ; A letter enumerator tag.
    (num-prt "[0-9]") ; A number enumerator part.
    (num-tag num-prt "+") ; A number enumerator tag.
    (rom-prt "[IVXLCDMivxlcdm]") ; A roman enumerator part.
    (rom-tag rom-prt "+") ; A roman enumerator tag.
    (aut-tag "#") ; An automatic enumerator tag.
    (dcl-tag "::") ; Double colon.
254 255 256

    ;; Block lead in (`bli')
    (bli-sfx (:alt hws-sta "$")) ; Suffix of a block lead-in with *optional*
257
				 ; immediate content.
258 259

    ;; Various starts
260
    (bul-sta bul-tag bli-sfx) ; Start of a bulleted item.
261 262 263 264 265 266 267

    ;; Explicit markup tag (`exm')
    (exm-tag "\\.\\.")
    (exm-sta exm-tag hws-sta)
    (exm-beg lin-beg exm-sta)

    ;; Counters in enumerations (`cnt')
268 269
    (cntany-tag (:alt ltr-tag num-tag rom-tag aut-tag)) ; An arbitrary counter.
    (cntexp-tag (:alt ltr-tag num-tag rom-tag)) ; An arbitrary explicit counter.
270 271 272 273

    ;; Enumerator (`enm')
    (enmany-tag (:alt
		 (:seq cntany-tag "\\.")
274
		 (:seq "(?" cntany-tag ")"))) ; An arbitrary enumerator.
275 276 277
    (enmexp-tag (:alt
		 (:seq cntexp-tag "\\.")
		 (:seq "(?" cntexp-tag ")"))) ; An arbitrary explicit
278
					      ; enumerator.
279 280
    (enmaut-tag (:alt
		 (:seq aut-tag "\\.")
281 282 283
		 (:seq "(?" aut-tag ")"))) ; An automatic enumerator.
    (enmany-sta enmany-tag bli-sfx) ; An arbitrary enumerator start.
    (enmexp-sta enmexp-tag bli-sfx) ; An arbitrary explicit enumerator start.
284
    (enmexp-beg lin-beg enmexp-sta) ; An arbitrary explicit enumerator start
285
				    ; at the beginning of a line.
286 287

    ;; Items may be enumerated or bulleted (`itm')
288
    (itmany-tag (:alt enmany-tag bul-tag)) ; An arbitrary item tag.
289
    (itmany-sta-1 (:grp itmany-tag) bli-sfx) ; An arbitrary item start, group
290
					     ; is the item tag.
291 292
    (itmany-beg-1 lin-beg itmany-sta-1) ; An arbitrary item start at the
				        ; beginning of a line, group is the
293
				        ; item tag.
294 295 296 297 298 299

    ;; Inline markup (`ilm')
    (ilm-pfx (:alt "^" hws-prt "[-'\"([{<\u2018\u201c\u00ab\u2019/:]"))
    (ilm-sfx (:alt "$" hws-prt "[]-'\")}>\u2019\u201d\u00bb/:.,;!?\\]"))

    ;; Inline markup content (`ilc')
300 301 302
    (ilcsgl-tag "\\S ") ; A single non-white character.
    (ilcast-prt (:alt "[^*\\]" "\\\\.")) ; Part of non-asterisk content.
    (ilcbkq-prt (:alt "[^`\\]" "\\\\.")) ; Part of non-backquote content.
303
    (ilcbkqdef-prt (:alt "[^`\\\n]" "\\\\.")) ; Part of non-backquote
304 305
					      ; definition.
    (ilcbar-prt (:alt "[^|\\]" "\\\\.")) ; Part of non-vertical-bar content.
306
    (ilcbardef-prt (:alt "[^|\\\n]" "\\\\.")) ; Part of non-vertical-bar
307 308 309 310 311
					      ; definition.
    (ilcast-sfx "[^\t *\\]") ; Suffix of non-asterisk content.
    (ilcbkq-sfx "[^\t `\\]") ; Suffix of non-backquote content.
    (ilcbar-sfx "[^\t |\\]") ; Suffix of non-vertical-bar content.
    (ilcrep-hlp ,(format "\\{0,%d\\}" rst-max-inline-length)) ; Repeat count.
312 313 314
    (ilcast-tag (:alt ilcsgl-tag
		      (:seq ilcsgl-tag
			    ilcast-prt ilcrep-hlp
315
			    ilcast-sfx))) ; Non-asterisk content.
316 317 318
    (ilcbkq-tag (:alt ilcsgl-tag
		      (:seq ilcsgl-tag
			    ilcbkq-prt ilcrep-hlp
319
			    ilcbkq-sfx))) ; Non-backquote content.
320 321 322
    (ilcbkqdef-tag (:alt ilcsgl-tag
			 (:seq ilcsgl-tag
			       ilcbkqdef-prt ilcrep-hlp
323
			       ilcbkq-sfx))) ; Non-backquote definition.
324 325 326
    (ilcbar-tag (:alt ilcsgl-tag
		      (:seq ilcsgl-tag
			    ilcbar-prt ilcrep-hlp
327
			    ilcbar-sfx))) ; Non-vertical-bar content.
328 329 330
    (ilcbardef-tag (:alt ilcsgl-tag
			 (:seq ilcsgl-tag
			       ilcbardef-prt ilcrep-hlp
331
			       ilcbar-sfx))) ; Non-vertical-bar definition.
332 333

    ;; Fields (`fld')
334 335 336
    (fldnam-prt (:alt "[^:\n]" "\\\\:")) ; Part of a field name.
    (fldnam-tag fldnam-prt "+") ; A field name.
    (fld-tag ":" fldnam-tag ":") ; A field marker.
337 338

    ;; Options (`opt')
339 340 341 342 343
    (optsta-tag (:alt "[-+/]" "--")) ; Start of an option.
    (optnam-tag "\\sw" (:alt "-" "\\sw") "*") ; Name of an option.
    (optarg-tag (:shy "[ =]\\S +")) ; Option argument.
    (optsep-tag (:shy "," hws-prt)) ; Separator between options.
    (opt-tag (:shy optsta-tag optnam-tag optarg-tag "?")) ; A complete option.
344 345

    ;; Footnotes and citations (`fnc')
346 347 348
    (fncnam-prt "[^\]\n]") ; Part of a footnote or citation name.
    (fncnam-tag fncnam-prt "+") ; A footnote or citation name.
    (fnc-tag "\\[" fncnam-tag "]") ; A complete footnote or citation tag.
349 350
    (fncdef-tag-2 (:grp exm-sta)
		  (:grp fnc-tag)) ; A complete footnote or citation definition
351
				  ; tag.  First group is the explicit markup
352
				  ; start, second group is the footnote /
353
				  ; citation tag.
354
    (fnc-sta-2 fncdef-tag-2 bli-sfx) ; Start of a footnote or citation
355
				     ; definition.  First group is the explicit
356
				     ; markup start, second group is the
357
				     ; footnote / citation tag.
358 359

    ;; Substitutions (`sub')
360
    (sub-tag "|" ilcbar-tag "|") ; A complete substitution tag.
361
    (subdef-tag "|" ilcbardef-tag "|") ; A complete substitution definition
362
				       ; tag.
363 364 365 366 367 368 369 370 371 372 373

    ;; Symbol (`sym')
    (sym-tag (:shy "\\sw+" (:shy "\\s_\\sw+") "*"))

    ;; URIs (`uri')
    (uri-tag (:alt ,@rst-uri-schemes))

    ;; Adornment (`ado')
    (ado-prt "[" ,(concat rst-adornment-chars) "]")
    (adorep3-hlp "\\{3,\\}") ; There must be at least 3 characters because
			     ; otherwise explicit markup start would be
374
			     ; recognized.
375
    (adorep2-hlp "\\{2,\\}") ; As `adorep3-hlp' but when the first of three
376
			     ; characters is matched differently.
377 378 379
    (ado-tag-1-1 (:grp ado-prt)
		 "\\1" adorep2-hlp) ; A complete adornment, group is the first
				    ; adornment character and MUST be the FIRST
380
				    ; group in the whole expression.
381 382 383
    (ado-tag-1-2 (:grp ado-prt)
		 "\\2" adorep2-hlp) ; A complete adornment, group is the first
				    ; adornment character and MUST be the
384
				    ; SECOND group in the whole expression.
385 386 387 388
    (ado-beg-2-1 "^" (:grp ado-tag-1-2)
		 lin-end) ; A complete adornment line; first group is the whole
			  ; adornment and MUST be the FIRST group in the whole
			  ; expression; second group is the first adornment
389
			  ; character.
390 391

    ;; Titles (`ttl')
392 393
    (ttl-tag "\\S *\\w\\S *") ; A title text.
    (ttl-beg lin-beg ttl-tag) ; A title text at the beginning of a line.
394 395 396 397 398

    ;; Directives and substitution definitions (`dir')
    (dir-tag-3 (:grp exm-sta)
	       (:grp (:shy subdef-tag hws-sta) "?")
	       (:grp sym-tag dcl-tag)) ; A directive or substitution definition
399
				       ; tag.  First group is explicit markup
400 401 402
				       ; start, second group is a possibly
				       ; empty substitution tag, third group is
				       ; the directive tag including the double
403
				       ; colon.
404
    (dir-sta-3 dir-tag-3 bli-sfx) ; Start of a directive or substitution
405
				  ; definition.  Groups are as in dir-tag-3.
406 407 408

    ;; Literal block (`lit')
    (lit-sta-2 (:grp (:alt "[^.\n]" "\\.[^.\n]") ".*") "?"
409
	       (:grp dcl-tag) "$") ; Start of a literal block.  First group is
410 411
				   ; any text before the double colon tag which
				   ; may not exist, second group is the double
412
				   ; colon tag.
413 414 415 416 417

    ;; Comments (`cmt')
    (cmt-sta-1 (:grp exm-sta) "[^\[|_\n]"
	       (:alt "[^:\n]" (:seq ":" (:alt "[^:\n]" "$")))
	       "*$") ; Start of a comment block; first group is explicit markup
418
		     ; start.
419 420 421 422

    ;; Paragraphs (`par')
    (par-tag- (:alt itmany-tag fld-tag opt-tag fncdef-tag-2 dir-tag-3 exm-tag)
	      ) ; Tag at the beginning of a paragraph; there may be groups in
423
		; certain cases.
424 425 426 427 428
    )
  "Definition alist of relevant regexes.
Each entry consists of the symbol naming the regex and an
argument list for `rst-re'.")

429
;; FIXME: Use `sregex` or `rx` instead of re-inventing the wheel.
430 431 432 433 434 435 436 437 438 439
(defun rst-re (&rest args)
  "Interpret ARGS as regular expressions and return a regex string.
Each element of ARGS may be one of the following:

A string which is inserted unchanged.

A character which is resolved to a quoted regex.

A symbol which is resolved to a string using `rst-re-alist-def'.

440 441
A list with a keyword in the car.  Each element of the cdr of such
a list is recursively interpreted as ARGS.  The results of this
442 443 444 445 446 447 448 449 450 451 452
interpretation are concatenated according to the keyword.

For the keyword `:seq' the results are simply concatenated.

For the keyword `:shy' the results are concatenated and
surrounded by a shy-group (\"\\(?:...\\)\").

For the keyword `:alt' the results form an alternative (\"\\|\")
which is shy-grouped (\"\\(?:...\\)\").

For the keyword `:grp' the results are concatenated and form a
453
referenceable group (\"\\(...\\)\").
454 455

After interpretation of ARGS the results are concatenated as for
456
`:seq'."
457 458 459 460 461 462 463 464
  (apply 'concat
	 (mapcar
	  (lambda (re)
	    (cond
	     ((stringp re)
	      re)
	     ((symbolp re)
	      (cadr (assoc re rst-re-alist)))
465
	     ((characterp re)
466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486
	      (regexp-quote (char-to-string re)))
	     ((listp re)
	      (let ((nested
		     (mapcar (lambda (elt)
			       (rst-re elt))
			     (cdr re))))
		(cond
		 ((eq (car re) :seq)
		  (mapconcat 'identity nested ""))
		 ((eq (car re) :shy)
		  (concat "\\(?:" (mapconcat 'identity nested "") "\\)"))
		 ((eq (car re) :grp)
		  (concat "\\(" (mapconcat 'identity nested "") "\\)"))
		 ((eq (car re) :alt)
		  (concat "\\(?:" (mapconcat 'identity nested "\\|") "\\)"))
		 (t
		  (error "Unknown list car: %s" (car re))))))
	     (t
	      (error "Unknown object type for building regex: %s" re))))
	  args)))

487 488 489
;; FIXME: Remove circular dependency between `rst-re' and `rst-re-alist'.
(defconst rst-re-alist
  ;; Shadow global value we are just defining so we can construct it step by
490
  ;; step.
491 492 493 494 495 496 497 498
  (let (rst-re-alist)
    (dolist (re rst-re-alist-def)
      (setq rst-re-alist
	    (nconc rst-re-alist
		   (list (list (car re) (apply 'rst-re (cdr re)))))))
    rst-re-alist)
  "Alist mapping symbols from `rst-re-alist-def' to regex strings.")

Stefan Monnier's avatar
Stefan Monnier committed
499 500

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
501
;; Mode definition
502 503

(defun rst-define-key (keymap key def &rest deprecated)
504 505 506 507
  "Bind like `define-key' but add deprecated key definitions.
KEYMAP, KEY, and DEF are as in `define-key'.  DEPRECATED key
definitions should be in vector notation.  These are defined as
well but give an additional message."
508 509
  (define-key keymap key def)
  (dolist (dep-key deprecated)
510 511 512 513 514 515 516 517
    (define-key keymap dep-key
      `(lambda ()
         ,(format "Deprecated binding for %s, use \\[%s] instead." def def)
	 (interactive)
	 (call-interactively ',def)
	 (message "[Deprecated use of key %s; use key %s instead]"
		  (key-description (this-command-keys))
		  (key-description ,key))))))
518

Stefan Monnier's avatar
Stefan Monnier committed
519 520 521 522
;; Key bindings.
(defvar rst-mode-map
  (let ((map (make-sparse-keymap)))

523
    ;; \C-c is the general keymap.
524 525
    (rst-define-key map [?\C-c ?\C-h] 'describe-prefix-bindings)

Stefan Monnier's avatar
Stefan Monnier committed
526
    ;;
527
    ;; Section Adornments
Stefan Monnier's avatar
Stefan Monnier committed
528
    ;;
529 530 531 532
    ;; The adjustment function that adorns or rotates a section title.
    (rst-define-key map [?\C-c ?\C-=] 'rst-adjust [?\C-c ?\C-a t])
    (rst-define-key map [?\C-=] 'rst-adjust) ; (Does not work on the Mac OSX.)

533
    ;; \C-c \C-a is the keymap for adornments.
534
    (rst-define-key map [?\C-c ?\C-a ?\C-h] 'describe-prefix-bindings)
535 536
    ;; Display the hierarchy of adornments implied by the current document
    ;; contents.
537 538 539 540
    (rst-define-key map [?\C-c ?\C-a ?\C-d] 'rst-display-adornments-hierarchy)
    ;; Homogenize the adornments in the document.
    (rst-define-key map [?\C-c ?\C-a ?\C-s] 'rst-straighten-adornments
		    [?\C-c ?\C-s])
Stefan Monnier's avatar
Stefan Monnier committed
541 542

    ;;
543
    ;; Section Movement and Selection
Stefan Monnier's avatar
Stefan Monnier committed
544 545
    ;;
    ;; Mark the subsection where the cursor is.
546
    (rst-define-key map [?\C-\M-h] 'rst-mark-section
547
		    ;; Same as mark-defun sgml-mark-current-element.
548
		    [?\C-c ?\C-m])
549 550
    ;; Move backward/forward between section titles.
    (rst-define-key map [?\C-\M-a] 'rst-backward-section
551
		    ;; Same as beginning-of-defun.
552
		    [?\C-c ?\C-n])
553
    (rst-define-key map [?\C-\M-e] 'rst-forward-section
554
		    ;; Same as end-of-defun.
555
		    [?\C-c ?\C-p])
Stefan Monnier's avatar
Stefan Monnier committed
556 557

    ;;
558
    ;; Operating on regions
Stefan Monnier's avatar
Stefan Monnier committed
559
    ;;
560
    ;; \C-c \C-r is the keymap for regions.
561 562 563 564
    (rst-define-key map [?\C-c ?\C-r ?\C-h] 'describe-prefix-bindings)
    ;; Makes region a line-block.
    (rst-define-key map [?\C-c ?\C-r ?\C-l] 'rst-line-block-region
		    [?\C-c ?\C-d])
565
    ;; Shift region left or right according to tabs.
566 567 568 569
    (rst-define-key map [?\C-c ?\C-r tab] 'rst-shift-region
		    [?\C-c ?\C-r t] [?\C-c ?\C-l t])

    ;;
570
    ;; Operating on lists
571
    ;;
572
    ;; \C-c \C-l is the keymap for lists.
573
    (rst-define-key map [?\C-c ?\C-l ?\C-h] 'describe-prefix-bindings)
Stefan Monnier's avatar
Stefan Monnier committed
574
    ;; Makes paragraphs in region as a bullet list.
575 576
    (rst-define-key map [?\C-c ?\C-l ?\C-b] 'rst-bullet-list-region
		    [?\C-c ?\C-b])
Stefan Monnier's avatar
Stefan Monnier committed
577
    ;; Makes paragraphs in region as a enumeration.
578 579
    (rst-define-key map [?\C-c ?\C-l ?\C-e] 'rst-enumerate-region
		    [?\C-c ?\C-e])
Stefan Monnier's avatar
Stefan Monnier committed
580
    ;; Converts bullets to an enumeration.
581 582
    (rst-define-key map [?\C-c ?\C-l ?\C-c] 'rst-convert-bullets-to-enumeration
		    [?\C-c ?\C-v])
Stefan Monnier's avatar
Stefan Monnier committed
583
    ;; Make sure that all the bullets in the region are consistent.
584 585
    (rst-define-key map [?\C-c ?\C-l ?\C-s] 'rst-straighten-bullets-region
		    [?\C-c ?\C-w])
586
    ;; Insert a list item.
587
    (rst-define-key map [?\C-c ?\C-l ?\C-i] 'rst-insert-list)
Stefan Monnier's avatar
Stefan Monnier committed
588 589

    ;;
590
    ;; Table-of-Contents Features
Stefan Monnier's avatar
Stefan Monnier committed
591
    ;;
592
    ;; \C-c \C-t is the keymap for table of contents.
593
    (rst-define-key map [?\C-c ?\C-t ?\C-h] 'describe-prefix-bindings)
Stefan Monnier's avatar
Stefan Monnier committed
594
    ;; Enter a TOC buffer to view and move to a specific section.
595
    (rst-define-key map [?\C-c ?\C-t ?\C-t] 'rst-toc)
Stefan Monnier's avatar
Stefan Monnier committed
596
    ;; Insert a TOC here.
597 598
    (rst-define-key map [?\C-c ?\C-t ?\C-i] 'rst-toc-insert
		    [?\C-c ?\C-i])
Stefan Monnier's avatar
Stefan Monnier committed
599
    ;; Update the document's TOC (without changing the cursor position).
600 601
    (rst-define-key map [?\C-c ?\C-t ?\C-u] 'rst-toc-update
		    [?\C-c ?\C-u])
602
    ;; Go to the section under the cursor (cursor must be in TOC).
603 604
    (rst-define-key map [?\C-c ?\C-t ?\C-j] 'rst-goto-section
		    [?\C-c ?\C-f])
Stefan Monnier's avatar
Stefan Monnier committed
605 606

    ;;
607
    ;; Converting Documents from Emacs
Stefan Monnier's avatar
Stefan Monnier committed
608
    ;;
609
    ;; \C-c \C-c is the keymap for compilation.
610
    (rst-define-key map [?\C-c ?\C-c ?\C-h] 'describe-prefix-bindings)
Stefan Monnier's avatar
Stefan Monnier committed
611
    ;; Run one of two pre-configured toolset commands on the document.
612 613 614 615
    (rst-define-key map [?\C-c ?\C-c ?\C-c] 'rst-compile
		    [?\C-c ?1])
    (rst-define-key map [?\C-c ?\C-c ?\C-a] 'rst-compile-alt-toolset
		    [?\C-c ?2])
Stefan Monnier's avatar
Stefan Monnier committed
616
    ;; Convert the active region to pseudo-xml using the docutils tools.
617 618
    (rst-define-key map [?\C-c ?\C-c ?\C-x] 'rst-compile-pseudo-region
		    [?\C-c ?3])
Stefan Monnier's avatar
Stefan Monnier committed
619
    ;; Convert the current document to PDF and launch a viewer on the results.
620 621
    (rst-define-key map [?\C-c ?\C-c ?\C-p] 'rst-compile-pdf-preview
		    [?\C-c ?4])
Stefan Monnier's avatar
Stefan Monnier committed
622
    ;; Convert the current document to S5 slides and view in a web browser.
623 624
    (rst-define-key map [?\C-c ?\C-c ?\C-s] 'rst-compile-slides-preview
		    [?\C-c ?5])
Stefan Monnier's avatar
Stefan Monnier committed
625 626

    map)
627
  "Keymap for reStructuredText mode commands.
Stefan Monnier's avatar
Stefan Monnier committed
628
This inherits from Text mode.")
Stefan Monnier's avatar
Stefan Monnier committed
629 630 631 632


;; Abbrevs.
(define-abbrev-table 'rst-mode-abbrev-table
633 634 635 636 637 638 639
  (mapcar (lambda (x) (append x '(nil 0 system)))
          '(("contents" ".. contents::\n..\n   ")
            ("con" ".. contents::\n..\n   ")
            ("cont" "[...]")
            ("skip" "\n\n[...]\n\n  ")
            ("seq" "\n\n[...]\n\n  ")
            ;; FIXME: Add footnotes, links, and more.
640 641
            ))
  "Abbrev table used while in `rst-mode'.")
Stefan Monnier's avatar
Stefan Monnier committed
642 643 644 645 646 647 648 649 650 651 652


;; Syntax table.
(defvar rst-mode-syntax-table
  (let ((st (copy-syntax-table text-mode-syntax-table)))

    (modify-syntax-entry ?$ "." st)
    (modify-syntax-entry ?% "." st)
    (modify-syntax-entry ?& "." st)
    (modify-syntax-entry ?' "." st)
    (modify-syntax-entry ?* "." st)
653
    (modify-syntax-entry ?+ "_" st)
Stefan Monnier's avatar
Stefan Monnier committed
654 655
    (modify-syntax-entry ?. "_" st)
    (modify-syntax-entry ?/ "." st)
656
    (modify-syntax-entry ?: "_" st)
Stefan Monnier's avatar
Stefan Monnier committed
657 658 659 660 661
    (modify-syntax-entry ?< "." st)
    (modify-syntax-entry ?= "." st)
    (modify-syntax-entry ?> "." st)
    (modify-syntax-entry ?\\ "\\" st)
    (modify-syntax-entry ?| "." st)
662 663 664 665 666 667 668
    (modify-syntax-entry ?_ "_" st)
    (modify-syntax-entry ?\u00ab "." st)
    (modify-syntax-entry ?\u00bb "." st)
    (modify-syntax-entry ?\u2018 "." st)
    (modify-syntax-entry ?\u2019 "." st)
    (modify-syntax-entry ?\u201c "." st)
    (modify-syntax-entry ?\u201d "." st)
Stefan Monnier's avatar
Stefan Monnier committed
669 670 671 672 673 674

    st)
  "Syntax table used while in `rst-mode'.")


(defcustom rst-mode-hook nil
675 676
  "Hook run when `rst-mode' is turned on.
The hook for `text-mode' is run before this one."
Stefan Monnier's avatar
Stefan Monnier committed
677 678 679 680
  :group 'rst
  :type '(hook))


681 682
;; Use rst-mode for *.rst and *.rest files.  Many ReStructured-Text files
;; use *.txt, but this is too generic to be set as a default.
683
;;;###autoload (add-to-list 'auto-mode-alist (purecopy '("\\.re?st\\'" . rst-mode)))
Stefan Monnier's avatar
Stefan Monnier committed
684 685 686
;;;###autoload
(define-derived-mode rst-mode text-mode "ReST"
  "Major mode for editing reStructuredText documents.
687
\\<rst-mode-map>
Stefan Monnier's avatar
Stefan Monnier committed
688

689 690
Turning on `rst-mode' calls the normal hooks `text-mode-hook'
and `rst-mode-hook'.  This mode also supports font-lock
691
highlighting.
692 693

\\{rst-mode-map}"
694 695 696
  :abbrev-table rst-mode-abbrev-table
  :syntax-table rst-mode-syntax-table
  :group 'rst
Stefan Monnier's avatar
Stefan Monnier committed
697

698
  ;; Paragraph recognition.
699 700 701 702
  (set (make-local-variable 'paragraph-separate)
       (rst-re '(:alt
		 "\f"
		 lin-end)))
Stefan Monnier's avatar
Stefan Monnier committed
703
  (set (make-local-variable 'paragraph-start)
704 705 706 707
       (rst-re '(:alt
		 "\f"
		 lin-end
		 (:seq hws-tag par-tag- bli-sfx))))
Stefan Monnier's avatar
Stefan Monnier committed
708

709
  ;; Indenting and filling.
710 711 712 713 714 715
  (set (make-local-variable 'indent-line-function) 'rst-indent-line)
  (set (make-local-variable 'adaptive-fill-mode) t)
  (set (make-local-variable 'adaptive-fill-regexp)
       (rst-re 'hws-tag 'par-tag- "?" 'hws-tag))
  (set (make-local-variable 'adaptive-fill-function) 'rst-adaptive-fill)
  (set (make-local-variable 'fill-paragraph-handle-comment) nil)
Stefan Monnier's avatar
Stefan Monnier committed
716

717
  ;; Comments.
Stefan Monnier's avatar
Stefan Monnier committed
718
  (set (make-local-variable 'comment-start) ".. ")
719 720 721 722 723 724
  (set (make-local-variable 'comment-start-skip)
       (rst-re 'lin-beg 'exm-tag 'bli-sfx))
  (set (make-local-variable 'comment-continue) "   ")
  (set (make-local-variable 'comment-multi-line) t)
  (set (make-local-variable 'comment-use-syntax) nil)
  ;; reStructuredText has not really a comment ender but nil is not really a
725
  ;; permissible value.
726 727 728
  (set (make-local-variable 'comment-end) "")
  (set (make-local-variable 'comment-end-skip) nil)

729 730
  ;; Commenting in reStructuredText is very special so use our own set of
  ;; functions.
731 732 733 734 735 736 737 738 739 740
  (set (make-local-variable 'comment-line-break-function)
       'rst-comment-line-break)
  (set (make-local-variable 'comment-indent-function)
       'rst-comment-indent)
  (set (make-local-variable 'comment-insert-comment-function)
       'rst-comment-insert-comment)
  (set (make-local-variable 'comment-region-function)
       'rst-comment-region)
  (set (make-local-variable 'uncomment-region-function)
       'rst-uncomment-region)
Stefan Monnier's avatar
Stefan Monnier committed
741

742 743 744 745 746 747
  ;; Font lock.
  (set (make-local-variable 'font-lock-defaults)
       '(rst-font-lock-keywords
	 t nil nil nil
	 (font-lock-multiline . t)
	 (font-lock-mark-block-function . mark-paragraph)))
748 749
  (add-hook 'font-lock-extend-region-functions 'rst-font-lock-extend-region t)

750
  ;; Text after a changed line may need new fontification.
751
  (set (make-local-variable 'jit-lock-contextually) t))
Stefan Monnier's avatar
Stefan Monnier committed
752 753 754

;;;###autoload
(define-minor-mode rst-minor-mode
Chong Yidong's avatar
Chong Yidong committed
755 756 757 758
  "Toggle ReST minor mode.
With a prefix argument ARG, enable ReST minor mode if ARG is
positive, and disable it otherwise.  If called from Lisp, enable
the mode if ARG is omitted or nil.
Stefan Monnier's avatar
Stefan Monnier committed
759

Juanma Barranquero's avatar
Juanma Barranquero committed
760 761 762
When ReST minor mode is enabled, the ReST mode keybindings
are installed on top of the major mode bindings.  Use this
for modes derived from Text mode, like Mail mode."
Stefan Monnier's avatar
Stefan Monnier committed
763 764 765 766 767 768 769 770 771
 ;; The initial value.
 nil
 ;; The indicator for the mode line.
 " ReST"
 ;; The minor mode bindings.
 rst-mode-map
 :group 'rst)

;; FIXME: can I somehow install these too?
772 773
;;        :abbrev-table rst-mode-abbrev-table
;;        :syntax-table rst-mode-syntax-table
Stefan Monnier's avatar
Stefan Monnier committed
774 775 776


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
777 778
;; Section Adornment Adjustment
;; ============================
Stefan Monnier's avatar
Stefan Monnier committed
779 780 781 782 783
;;
;; The following functions implement a smart automatic title sectioning feature.
;; The idea is that with the cursor sitting on a section title, we try to get as
;; much information from context and try to do the best thing automatically.
;; This function can be invoked many times and/or with prefix argument to rotate
784
;; between the various sectioning adornments.
Stefan Monnier's avatar
Stefan Monnier committed
785 786
;;
;; Definitions: the two forms of sectioning define semantically separate section
787
;; levels.  A sectioning ADORNMENT consists in:
Stefan Monnier's avatar
Stefan Monnier committed
788 789 790 791 792 793 794 795 796
;;
;;   - a CHARACTER
;;
;;   - a STYLE which can be either of 'simple' or 'over-and-under'.
;;
;;   - an INDENT (meaningful for the over-and-under style only) which determines
;;     how many characters and over-and-under style is hanging outside of the
;;     title at the beginning and ending.
;;
797
;; Here are two examples of adornments (| represents the window border, column
Stefan Monnier's avatar
Stefan Monnier committed
798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813
;; 0):
;;
;;                                  |
;; 1. char: '-'   e                 |Some Title
;;    style: simple                 |----------
;;                                  |
;; 2. char: '='                     |==============
;;    style: over-and-under         |  Some Title
;;    indent: 2                     |==============
;;                                  |
;;
;; Some notes:
;;
;; - The underlining character that is used depends on context. The file is
;;   scanned to find other sections and an appropriate character is selected.
;;   If the function is invoked on a section that is complete, the character is
814
;;   rotated among the existing section adornments.
Stefan Monnier's avatar
Stefan Monnier committed
815 816
;;
;;   Note that when rotating the characters, if we come to the end of the
817 818 819 820
;;   hierarchy of adornments, the variable rst-preferred-adornments is
;;   consulted to propose a new underline adornment, and if continued, we cycle
;;   the adornments all over again.  Set this variable to nil if you want to
;;   limit the underlining character propositions to the existing adornments in
Stefan Monnier's avatar
Stefan Monnier committed
821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842
;;   the file.
;;
;; - An underline/overline that is not extended to the column at which it should
;;   be hanging is dubbed INCOMPLETE.  For example::
;;
;;      |Some Title
;;      |-------
;;
;; Examples of default invocation:
;;
;;   |Some Title       --->    |Some Title
;;   |                         |----------
;;
;;   |Some Title       --->    |Some Title
;;   |-----                    |----------
;;
;;   |                         |------------
;;   | Some Title      --->    | Some Title
;;   |                         |------------
;;
;; In over-and-under style, when alternating the style, a variable is
;; available to select how much default indent to use (it can be zero).  Note
843
;; that if the current section adornment already has an indent, we don't
Stefan Monnier's avatar
Stefan Monnier committed
844 845 846 847 848
;; adjust it to the default, we rather use the current indent that is already
;; there for adjustment (unless we cycle, in which case we use the indent
;; that has been found previously).

(defgroup rst-adjust nil
849
  "Settings for adjustment and cycling of section title adornments."
Stefan Monnier's avatar
Stefan Monnier committed
850 851 852
  :group 'rst
  :version "21.1")

853 854 855 856 857 858 859 860 861 862 863 864 865
(define-obsolete-variable-alias
  'rst-preferred-decorations 'rst-preferred-adornments "r6506")
(defcustom rst-preferred-adornments '((?= over-and-under 1)
				      (?= simple 0)
				      (?- simple 0)
				      (?~ simple 0)
				      (?+ simple 0)
				      (?` simple 0)
				      (?# simple 0)
				      (?@ simple 0))
  "Preferred hierarchy of section title adornments.

A list consisting of lists of the form (CHARACTER STYLE INDENT).
866 867 868 869
CHARACTER is the character used.  STYLE is one of the symbols
OVER-AND-UNDER or SIMPLE.  INDENT is an integer giving the wanted
indentation for STYLE OVER-AND-UNDER.  CHARACTER and STYLE are
always used when a section adornment is described.  In other
870 871 872
places t instead of a list stands for a transition.

This sequence is consulted to offer a new adornment suggestion
Stefan Monnier's avatar
Stefan Monnier committed
873 874
when we rotate the underlines at the end of the existing
hierarchy of characters, or when there is no existing section
875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891
title in the file.

Set this to an empty list to use only the adornment found in the
file."
  :group 'rst-adjust
  :type `(repeat
	  (group :tag "Adornment specification"
		 (choice :tag "Adornment character"
			 ,@(mapcar (lambda (char)
				     (list 'const
					   :tag (char-to-string char) char))
				   rst-adornment-chars))
		 (radio :tag "Adornment type"
			(const :tag "Overline and underline" over-and-under)
			(const :tag "Underline only" simple))
		 (integer :tag "Indentation for overline and underline type"
			  :value 0))))
Stefan Monnier's avatar
Stefan Monnier committed
892 893 894 895

(defcustom rst-default-indent 1
  "Number of characters to indent the section title.

896 897
This is used for when toggling adornment styles, when switching
from a simple adornment style to a over-and-under adornment
Stefan Monnier's avatar
Stefan Monnier committed
898
style."
899 900
  :group 'rst-adjust
  :type '(integer))
Stefan Monnier's avatar
Stefan Monnier committed
901 902


903 904 905
(defun rst-compare-adornments (ado1 ado2)
  "Compare adornments.
Return true if both ADO1 and ADO2 adornments are equal,
Stefan Monnier's avatar
Stefan Monnier committed
906
according to restructured text semantics (only the character and
Juanma Barranquero's avatar
Juanma Barranquero committed
907
the style are compared, the indentation does not matter)."
908 909
  (and (eq (car ado1) (car ado2))
       (eq (cadr ado1) (cadr ado2))))
Stefan Monnier's avatar
Stefan Monnier committed
910 911


912 913
(defun rst-get-adornment-match (hier ado)
  "Return the index (level) in hierarchy HIER of adornment ADO.
Stefan Monnier's avatar
Stefan Monnier committed
914
This basically just searches for the item using the appropriate
Juanma Barranquero's avatar
Juanma Barranquero committed
915
comparison and returns the index.  Return nil if the item is
Stefan Monnier's avatar
Stefan Monnier committed
916 917
not found."
  (let ((cur hier))
918
    (while (and cur (not (rst-compare-adornments (car cur) ado)))
Stefan Monnier's avatar
Stefan Monnier committed
919 920 921 922
      (setq cur (cdr cur)))
    cur))


923 924
(defun rst-suggest-new-adornment (allados &optional prev)
  "Suggest a new, different adornment from all that have been seen.
Stefan Monnier's avatar
Stefan Monnier committed
925

926 927
ALLADOS is the set of all adornments, including the line numbers.
PREV is the optional previous adornment, in order to suggest a
Juanma Barranquero's avatar
Juanma Barranquero committed
928
better match."
Stefan Monnier's avatar
Stefan Monnier committed
929

930
  ;; For all the preferred adornments...
Stefan Monnier's avatar
Stefan Monnier committed
931 932 933 934
  (let* (
         ;; If 'prev' is given, reorder the list to start searching after the
         ;; match.
         (fplist
935
          (cdr (rst-get-adornment-match rst-preferred-adornments prev)))
Stefan Monnier's avatar
Stefan Monnier committed
936 937

         ;; List of candidates to search.
938
         (curpotential (append fplist rst-preferred-adornments)))
Stefan Monnier's avatar
Stefan Monnier committed
939
    (while
940 941
        ;; For all the adornments...
        (let ((cur allados)
Stefan Monnier's avatar
Stefan Monnier committed
942 943
              found)
          (while (and cur (not found))
944
            (if (rst-compare-adornments (car cur) (car curpotential))
Stefan Monnier's avatar
Stefan Monnier committed
945 946 947 948 949 950 951
                ;; Found it!
                (setq found (car curpotential))
              (setq cur (cdr cur))))
          found)

      (setq curpotential (cdr curpotential)))

Stefan Monnier's avatar
Stefan Monnier committed
952
    (copy-sequence (car curpotential))))
Stefan Monnier's avatar
Stefan Monnier committed
953 954 955

(defun rst-delete-entire-line ()
  "Delete the entire current line without using the `kill-ring'."
Stefan Monnier's avatar
Stefan Monnier committed
956 957
  (delete-region (line-beginning-position)
                 (line-beginning-position 2)))
Stefan Monnier's avatar
Stefan Monnier committed
958 959

(defun rst-update-section (char style &optional indent)
960
  "Unconditionally update the style of a section adornment.
Stefan Monnier's avatar
Stefan Monnier committed
961

Juanma Barranquero's avatar
Juanma Barranquero committed
962 963 964 965
Do this using the given character CHAR, with STYLE 'simple
or 'over-and-under, and with indent INDENT.  If the STYLE
is 'simple, whitespace before the title is removed (indent
is always assumed to be 0).
Stefan Monnier's avatar
Stefan Monnier committed
966 967

If there are existing overline and/or underline from the
968 969 970
existing adornment, they are removed before adding the
requested adornment."
  (end-of-line)
971 972
  (let ((marker (point-marker))
        len)
Stefan Monnier's avatar
Stefan Monnier committed
973

974
      ;; Fixup whitespace at the beginning and end of the line.
Stefan Monnier's avatar
Stefan Monnier committed
975 976 977 978 979 980 981 982 983
      (if (or (null indent) (eq style 'simple))
          (setq indent 0))
      (beginning-of-line)
      (delete-horizontal-space)
      (insert (make-string indent ? ))

      (end-of-line)
      (delete-horizontal-space)

984
      ;; Set the current column, we're at the end of the title line.
Stefan Monnier's avatar
Stefan Monnier committed
985 986
      (setq len (+ (current-column) indent))

987
      ;; Remove previous line if it is an adornment.
Stefan Monnier's avatar
Stefan Monnier committed
988 989
      (save-excursion
        (forward-line -1)
990 991 992 993 994 995
	(if (and (looking-at (rst-re 'ado-beg-2-1))
		 ;; Avoid removing the underline of a title right above us.
		 (save-excursion (forward-line -1)
				 (not (looking-at (rst-re 'ttl-beg)))))
	    (rst-delete-entire-line)))

996
      ;; Remove following line if it is an adornment.
Stefan Monnier's avatar
Stefan Monnier committed
997 998
      (save-excursion
        (forward-line +1)
999 1000
        (if (looking-at (rst-re 'ado-beg-2-1))
	    (rst-delete-entire-line))
Stefan Monnier's avatar
Stefan Monnier committed
1001
        ;; Add a newline if we're at the end of the buffer, for the subsequence