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

106 107
(eval-when-compile
  (require 'cl))
Stefan Monnier's avatar
Stefan Monnier committed
108

109 110 111 112
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Versions

(defun rst-extract-version (delim-re head-re re tail-re var &optional default)
113 114 115
  "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."
116 117 118 119 120 121 122
  (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
123
;; control systems.
124
(defconst rst-cvs-header
125
  "$CVSHeader: sm/rst_el/rst.el,v 1.257.2.9 2012-05-29 19:53:00 stefan Exp $")
126 127 128
(defconst rst-cvs-rev
  (rst-extract-version "\\$" "CVSHeader: \\S + " "[0-9]+\\(?:\\.[0-9]+\\)+"
		       " .*" rst-cvs-header "0.0")
129
  "The CVS revision of this file.  CVS revision is the development revision.")
130 131 132 133
(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")
134
  "The CVS time stamp of this file.")
135

136
;; Use LastChanged... to really get information from SVN.
137 138 139 140 141 142 143 144
(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) $")
145
  "The SVN time stamp of this file.")
146

147
;; Maintained by the release process.
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
(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.
163 164
Starts with the current official version.  For developer versions
in parentheses follows the development revision and the time stamp.")
165 166 167 168 169 170 171 172 173 174 175 176 177

(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
178

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

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

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

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

;; Used to be customizable but really is not customizable but fixed by the reST
196
;; syntax.
197
(defconst rst-bullets
198
  ;; Sorted so they can form a character class when concatenated.
199 200 201 202 203 204 205 206 207 208
  '(?- ?* ?+ ?\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
209
  ;; Sorted so they can form a character class when concatenated.
210 211 212 213 214 215 216 217 218 219 220
  '(?\]
    ?! ?\" ?# ?$ ?% ?& ?' ?\( ?\) ?* ?+ ?, ?. ?/ ?: ?\; ?< ?= ?> ?? ?@ ?\[ ?\\
    ?^ ?_ ?` ?{ ?| ?} ?~
    ?-)
  "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
221 222 223 224 225 226 227 228
  ;; `*-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 *.
229 230 231 232 233 234
  ;;
  ;; A trailing number says how many referenceable groups are contained.
  `(

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

    ;; Lines (`lin')
239 240 241
    (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.
242 243 244

    ;; Various tags and parts
    (ell-tag "\\.\\.\\.") ; Ellipsis
245 246 247 248 249 250 251 252
    (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.
253 254 255

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

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

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

    ;; Counters in enumerations (`cnt')
267 268
    (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.
269 270 271 272

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

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

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

    ;; Inline markup content (`ilc')
299 300 301
    (ilcsgl-tag "\\S ") ; A single non-white character.
    (ilcast-prt (:alt "[^*\\]" "\\\\.")) ; Part of non-asterisk content.
    (ilcbkq-prt (:alt "[^`\\]" "\\\\.")) ; Part of non-backquote content.
302
    (ilcbkqdef-prt (:alt "[^`\\\n]" "\\\\.")) ; Part of non-backquote
303 304
					      ; definition.
    (ilcbar-prt (:alt "[^|\\]" "\\\\.")) ; Part of non-vertical-bar content.
305
    (ilcbardef-prt (:alt "[^|\\\n]" "\\\\.")) ; Part of non-vertical-bar
306 307 308 309 310
					      ; 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.
311 312 313
    (ilcast-tag (:alt ilcsgl-tag
		      (:seq ilcsgl-tag
			    ilcast-prt ilcrep-hlp
314
			    ilcast-sfx))) ; Non-asterisk content.
315 316 317
    (ilcbkq-tag (:alt ilcsgl-tag
		      (:seq ilcsgl-tag
			    ilcbkq-prt ilcrep-hlp
318
			    ilcbkq-sfx))) ; Non-backquote content.
319 320 321
    (ilcbkqdef-tag (:alt ilcsgl-tag
			 (:seq ilcsgl-tag
			       ilcbkqdef-prt ilcrep-hlp
322
			       ilcbkq-sfx))) ; Non-backquote definition.
323 324 325
    (ilcbar-tag (:alt ilcsgl-tag
		      (:seq ilcsgl-tag
			    ilcbar-prt ilcrep-hlp
326
			    ilcbar-sfx))) ; Non-vertical-bar content.
327 328 329
    (ilcbardef-tag (:alt ilcsgl-tag
			 (:seq ilcsgl-tag
			       ilcbardef-prt ilcrep-hlp
330
			       ilcbar-sfx))) ; Non-vertical-bar definition.
331 332

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

    ;; Options (`opt')
338 339 340 341 342
    (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.
343 344

    ;; Footnotes and citations (`fnc')
345 346 347
    (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.
348 349
    (fncdef-tag-2 (:grp exm-sta)
		  (:grp fnc-tag)) ; A complete footnote or citation definition
350
				  ; tag.  First group is the explicit markup
351
				  ; start, second group is the footnote /
352
				  ; citation tag.
353
    (fnc-sta-2 fncdef-tag-2 bli-sfx) ; Start of a footnote or citation
354
				     ; definition.  First group is the explicit
355
				     ; markup start, second group is the
356
				     ; footnote / citation tag.
357 358

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

    ;; 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
373
			     ; recognized.
374
    (adorep2-hlp "\\{2,\\}") ; As `adorep3-hlp' but when the first of three
375
			     ; characters is matched differently.
376 377 378
    (ado-tag-1-1 (:grp ado-prt)
		 "\\1" adorep2-hlp) ; A complete adornment, group is the first
				    ; adornment character and MUST be the FIRST
379
				    ; group in the whole expression.
380 381 382
    (ado-tag-1-2 (:grp ado-prt)
		 "\\2" adorep2-hlp) ; A complete adornment, group is the first
				    ; adornment character and MUST be the
383
				    ; SECOND group in the whole expression.
384 385 386 387
    (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
388
			  ; character.
389 390

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

    ;; 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
398
				       ; tag.  First group is explicit markup
399 400 401
				       ; start, second group is a possibly
				       ; empty substitution tag, third group is
				       ; the directive tag including the double
402
				       ; colon.
403
    (dir-sta-3 dir-tag-3 bli-sfx) ; Start of a directive or substitution
404
				  ; definition.  Groups are as in dir-tag-3.
405 406 407

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

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

    ;; 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
422
		; certain cases.
423 424 425 426 427
    )
  "Definition alist of relevant regexes.
Each entry consists of the symbol naming the regex and an
argument list for `rst-re'.")

428
;; FIXME: Use `sregex` or `rx` instead of re-inventing the wheel.
429 430 431 432 433 434 435 436 437 438
(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'.

439 440
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
441 442 443 444 445 446 447 448 449 450 451
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
452
referenceable group (\"\\(...\\)\").
453 454

After interpretation of ARGS the results are concatenated as for
455
`:seq'."
456 457 458 459 460 461 462 463
  (apply 'concat
	 (mapcar
	  (lambda (re)
	    (cond
	     ((stringp re)
	      re)
	     ((symbolp re)
	      (cadr (assoc re rst-re-alist)))
464
	     ((characterp re)
465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485
	      (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)))

486 487 488
;; 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
489
  ;; step.
490 491 492 493 494 495 496 497
  (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
498 499

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
500
;; Mode definition
501 502

(defun rst-define-key (keymap key def &rest deprecated)
503 504 505 506
  "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."
507 508
  (define-key keymap key def)
  (dolist (dep-key deprecated)
509 510 511 512 513 514 515 516
    (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))))))
517

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

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

Stefan Monnier's avatar
Stefan Monnier committed
525
    ;;
526
    ;; Section Adornments
Stefan Monnier's avatar
Stefan Monnier committed
527
    ;;
528 529 530 531
    ;; 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.)

532
    ;; \C-c \C-a is the keymap for adornments.
533
    (rst-define-key map [?\C-c ?\C-a ?\C-h] 'describe-prefix-bindings)
534 535
    ;; Display the hierarchy of adornments implied by the current document
    ;; contents.
536 537 538 539
    (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
540 541

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

    ;;
557
    ;; Operating on regions
Stefan Monnier's avatar
Stefan Monnier committed
558
    ;;
559
    ;; \C-c \C-r is the keymap for regions.
560 561 562 563
    (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])
564
    ;; Shift region left or right according to tabs.
565 566 567 568
    (rst-define-key map [?\C-c ?\C-r tab] 'rst-shift-region
		    [?\C-c ?\C-r t] [?\C-c ?\C-l t])

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

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

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

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


;; Abbrevs.
(define-abbrev-table 'rst-mode-abbrev-table
632 633 634 635 636 637 638
  (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.
639 640
            ))
  "Abbrev table used while in `rst-mode'.")
Stefan Monnier's avatar
Stefan Monnier committed
641 642 643 644 645 646 647 648 649 650 651


;; 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)
652
    (modify-syntax-entry ?+ "_" st)
Stefan Monnier's avatar
Stefan Monnier committed
653 654
    (modify-syntax-entry ?. "_" st)
    (modify-syntax-entry ?/ "." st)
655
    (modify-syntax-entry ?: "_" st)
Stefan Monnier's avatar
Stefan Monnier committed
656 657 658 659 660
    (modify-syntax-entry ?< "." st)
    (modify-syntax-entry ?= "." st)
    (modify-syntax-entry ?> "." st)
    (modify-syntax-entry ?\\ "\\" st)
    (modify-syntax-entry ?| "." st)
661 662 663 664 665 666 667
    (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
668 669 670 671 672 673

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


(defcustom rst-mode-hook nil
674 675
  "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
676 677 678 679
  :group 'rst
  :type '(hook))


680 681
;; 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.
682
;;;###autoload (add-to-list 'auto-mode-alist (purecopy '("\\.re?st\\'" . rst-mode)))
Stefan Monnier's avatar
Stefan Monnier committed
683 684 685
;;;###autoload
(define-derived-mode rst-mode text-mode "ReST"
  "Major mode for editing reStructuredText documents.
686
\\<rst-mode-map>
Stefan Monnier's avatar
Stefan Monnier committed
687

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

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

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

708
  ;; Indenting and filling.
709 710 711 712 713 714
  (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
715

716
  ;; Comments.
Stefan Monnier's avatar
Stefan Monnier committed
717
  (set (make-local-variable 'comment-start) ".. ")
718 719 720 721 722 723
  (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
724
  ;; permissible value.
725 726 727
  (set (make-local-variable 'comment-end) "")
  (set (make-local-variable 'comment-end-skip) nil)

728 729
  ;; Commenting in reStructuredText is very special so use our own set of
  ;; functions.
730 731 732 733 734 735 736 737 738 739
  (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
740

741 742 743 744 745 746
  ;; 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)))
747 748
  (add-hook 'font-lock-extend-region-functions 'rst-font-lock-extend-region t)

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

;;;###autoload
(define-minor-mode rst-minor-mode
Chong Yidong's avatar
Chong Yidong committed
754 755 756 757
  "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
758

Juanma Barranquero's avatar
Juanma Barranquero committed
759 760 761
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
762 763 764 765 766 767 768 769 770
 ;; 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?
771 772
;;        :abbrev-table rst-mode-abbrev-table
;;        :syntax-table rst-mode-syntax-table
Stefan Monnier's avatar
Stefan Monnier committed
773 774 775


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
776 777
;; Section Adornment Adjustment
;; ============================
Stefan Monnier's avatar
Stefan Monnier committed
778 779 780 781 782
;;
;; 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
783
;; between the various sectioning adornments.
Stefan Monnier's avatar
Stefan Monnier committed
784 785
;;
;; Definitions: the two forms of sectioning define semantically separate section
786
;; levels.  A sectioning ADORNMENT consists in:
Stefan Monnier's avatar
Stefan Monnier committed
787 788 789 790 791 792 793 794 795
;;
;;   - 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.
;;
796
;; Here are two examples of adornments (| represents the window border, column
Stefan Monnier's avatar
Stefan Monnier committed
797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812
;; 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
813
;;   rotated among the existing section adornments.
Stefan Monnier's avatar
Stefan Monnier committed
814 815
;;
;;   Note that when rotating the characters, if we come to the end of the
816 817 818 819
;;   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
820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841
;;   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
842
;; that if the current section adornment already has an indent, we don't
Stefan Monnier's avatar
Stefan Monnier committed
843 844 845 846 847
;; 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
848
  "Settings for adjustment and cycling of section title adornments."
Stefan Monnier's avatar
Stefan Monnier committed
849 850 851
  :group 'rst
  :version "21.1")

852 853 854 855 856 857 858 859 860 861 862 863 864
(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).
865 866 867 868
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
869 870 871
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
872 873
when we rotate the underlines at the end of the existing
hierarchy of characters, or when there is no existing section
874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890
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
891 892 893 894

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

895 896
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
897
style."
898 899
  :group 'rst-adjust
  :type '(integer))
Stefan Monnier's avatar
Stefan Monnier committed
900 901


902 903 904
(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
905
according to restructured text semantics (only the character and
Juanma Barranquero's avatar
Juanma Barranquero committed
906
the style are compared, the indentation does not matter)."
907 908
  (and (eq (car ado1) (car ado2))
       (eq (cadr ado1) (cadr ado2))))
Stefan Monnier's avatar
Stefan Monnier committed
909 910


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


922 923
(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
924

925 926
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
927
better match."
Stefan Monnier's avatar
Stefan Monnier committed
928

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

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

      (setq curpotential (cdr curpotential)))

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

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

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

Juanma Barranquero's avatar
Juanma Barranquero committed
961 962 963 964
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
965 966

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

973
      ;; Fixup whitespace at the beginning and end of the line.
Stefan Monnier's avatar
Stefan Monnier committed
974 975 976 977 978 979 980 981 982
      (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)

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

986
      ;; Remove previous line if it is an adornment.
Stefan Monnier's avatar
Stefan Monnier committed
987 988
      (save-excursion
        (forward-line -1)
989 990 991 992 993 994
	(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)))

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