;;; Code:
+;; FIXME: Add proper ";;;###autoload" comments.
+
+;; FIXME: When 24.1 is common place remove use of `lexical-let' and put "-*-
+;; lexical-binding: t -*-" in the first line.
+
+;; Only use of macros is allowed - may be replaced by `cl-lib' some time.
(eval-when-compile
(require 'cl))
+;; Redefine some functions from `cl.el' in a proper namespace until they may be
+;; used from there.
+
+(defun rst-signum (x)
+ "Return 1 if X is positive, -1 if negative, 0 if zero."
+ (cond
+ ((> x 0) 1)
+ ((< x 0) -1)
+ (t 0)))
+
+(defun rst-some (seq &optional pred)
+ "Return non-nil if any element of SEQ yields non-nil when PRED is applied.
+Apply PRED to each element of list SEQ until the first non-nil
+result is yielded and return this result. PRED defaults to
+`identity'."
+ (unless pred
+ (setq pred 'identity))
+ (catch 'rst-some
+ (dolist (elem seq)
+ (let ((r (funcall pred elem)))
+ (when r
+ (throw 'rst-some r))))))
+
+(defun rst-position-if (pred seq)
+ "Return position of first element satisfying PRED in list SEQ or nil."
+ (catch 'rst-position-if
+ (let ((i 0))
+ (dolist (elem seq)
+ (when (funcall pred elem)
+ (throw 'rst-position-if i))
+ (incf i)))))
+
+(defun rst-position (elem seq)
+ "Return position of ELEM in list SEQ or nil.
+Comparison done with `equal'."
+ ;; Create a closure containing `elem' so the `lambda' always sees our
+ ;; parameter instead of an `elem' which may be in dynamic scope at the time
+ ;; of execution of the `lambda'.
+ (lexical-let ((elem elem))
+ (rst-position-if (function (lambda (e)
+ (equal elem e)))
+ seq)))
+
+;; FIXME: Embed complicated `defconst's in `eval-when-compile'.
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Versions
;; Use CVSHeader to really get information from CVS and not other version
;; control systems.
(defconst rst-cvs-header
- "$CVSHeader: sm/rst_el/rst.el,v 1.257.2.9 2012-05-29 19:53:00 stefan Exp $")
+ "$CVSHeader: sm/rst_el/rst.el,v 1.301 2012-07-30 19:29:46 stefan Exp $")
(defconst rst-cvs-rev
(rst-extract-version "\\$" "CVSHeader: \\S + " "[0-9]+\\(?:\\.[0-9]+\\)+"
" .*" rst-cvs-header "0.0")
;; Use LastChanged... to really get information from SVN.
(defconst rst-svn-rev
(rst-extract-version "\\$" "LastChangedRevision: " "[0-9]+" " "
- "$LastChangedRevision: 7399 $")
+ "$LastChangedRevision: 7490 $")
"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) $")
+ "$LastChangedDate: 2012-07-30 21:29:33 +0200 (Mon, 30 Jul 2012) $")
"The SVN time stamp of this file.")
;; Maintained by the release process.
(defconst rst-official-version
(rst-extract-version "%" "OfficialVersion: " "[0-9]+\\(?:\\.[0-9]+\\)+" " "
- "%OfficialVersion: 1.2.1 %")
+ "%OfficialVersion: 1.3.1 %")
"Official version of the package.")
(defconst rst-official-cvs-rev
(rst-extract-version "[%$]" "Revision: " "[0-9]+\\(?:\\.[0-9]+\\)+" " "
- "%Revision: 1.256 %")
+ "%Revision: 1.301 %")
"CVS revision of this file in the official version.")
(defconst rst-version
in parentheses follows the development revision and the time stamp.")
(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")))
+ '(("1.0.0" . "24.3")
+ ("1.1.0" . "24.3")
+ ("1.2.0" . "24.3")
+ ("1.2.1" . "24.3")
+ ("1.3.0" . "24.3")
+ ("1.3.1" . "24.3")
+ ))
(unless (assoc rst-official-version rst-package-emacs-version-alist)
(error "Version %s not listed in `rst-package-emacs-version-alist'"
; tag.
;; Symbol (`sym')
- (sym-tag (:shy "\\sw+" (:shy "\\s_\\sw+") "*"))
+ (sym-prt "[-+.:_]") ; Non-word part of a symbol.
+ (sym-tag (:shy "\\sw+" (:shy sym-prt "\\sw+") "*"))
;; URIs (`uri')
(uri-tag (:alt ,@rst-uri-schemes))
Each entry consists of the symbol naming the regex and an
argument list for `rst-re'.")
+(defvar rst-re-alist) ; Forward declare to use it in `rst-re'.
+
;; FIXME: Use `sregex` or `rx` instead of re-inventing the wheel.
(defun rst-re (&rest args)
"Interpret ARGS as regular expressions and return a regex string.
args)))
;; 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
- ;; step.
- (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.")
+(with-no-warnings ; Silence byte-compiler about this construction.
+ (defconst rst-re-alist
+ ;; Shadow global value we are just defining so we can construct it step by
+ ;; step.
+ (let (rst-re-alist)
+ (dolist (re rst-re-alist-def rst-re-alist)
+ (setq rst-re-alist
+ (nconc rst-re-alist
+ (list (list (car re) (apply 'rst-re (cdr re))))))))
+ "Alist mapping symbols from `rst-re-alist-def' to regex strings."))
\f
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; 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.)
+ (rst-define-key map [?\C-=] 'rst-adjust) ; Does not work on the Mac OSX and
+ ; on consoles.
;; \C-c \C-a is the keymap for adornments.
(rst-define-key map [?\C-c ?\C-a ?\C-h] 'describe-prefix-bindings)
+ ;; Another binding which works with all types of input.
+ (rst-define-key map [?\C-c ?\C-a ?\C-a] 'rst-adjust)
;; Display the hierarchy of adornments implied by the current document
;; contents.
(rst-define-key map [?\C-c ?\C-a ?\C-d] 'rst-display-adornments-hierarchy)
(rst-define-key map [?\C-\M-h] 'rst-mark-section
;; Same as mark-defun sgml-mark-current-element.
[?\C-c ?\C-m])
- ;; Move forward/backward between section titles.
- (rst-define-key map [?\C-\M-a] 'rst-forward-section
+ ;; Move backward/forward between section titles.
+ ;; FIXME: Also bind similar to outline mode.
+ (rst-define-key map [?\C-\M-a] 'rst-backward-section
;; Same as beginning-of-defun.
[?\C-c ?\C-n])
- (rst-define-key map [?\C-\M-e] 'rst-backward-section
+ (rst-define-key map [?\C-\M-e] 'rst-forward-section
;; Same as end-of-defun.
[?\C-c ?\C-p])
;; 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)
- (modify-syntax-entry ?+ "_" st)
- (modify-syntax-entry ?. "_" st)
+ (modify-syntax-entry ?+ "." st)
+ (modify-syntax-entry ?- "." st)
(modify-syntax-entry ?/ "." st)
- (modify-syntax-entry ?: "_" st)
(modify-syntax-entry ?< "." st)
(modify-syntax-entry ?= "." st)
(modify-syntax-entry ?> "." st)
(modify-syntax-entry ?\\ "\\" st)
+ (modify-syntax-entry ?_ "." st)
(modify-syntax-entry ?| "." st)
- (modify-syntax-entry ?_ "_" st)
(modify-syntax-entry ?\u00ab "." st)
(modify-syntax-entry ?\u00bb "." st)
(modify-syntax-entry ?\u2018 "." st)
:group 'rst
:type '(hook))
+;; Pull in variable definitions silencing byte-compiler.
+(require 'newcomment)
;; 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.
:version "21.1")
(define-obsolete-variable-alias
- 'rst-preferred-decorations 'rst-preferred-adornments "r6506")
+ 'rst-preferred-decorations 'rst-preferred-adornments "1.0.0")
(defcustom rst-preferred-adornments '((?= over-and-under 1)
(?= simple 0)
(?- simple 0)
))
)))
-(defun rst-position (elem list)
- "Return position of ELEM in LIST or nil."
- (let ((tail (member elem list)))
- (if tail (- (length list) (length tail)))))
-
(defun rst-straighten-adornments ()
"Redo all the adornments in the current buffer.
This is done using our preferred set of adornments. This can be
;; Apply the new style.
(apply 'rst-update-section (nth (car lm) rst-preferred-adornments))
- ;; Reset the market to avoid slowing down editing until it gets GC'ed.
+ ;; Reset the marker to avoid slowing down editing until it gets GC'ed.
(set-marker (cdr lm) nil)
)
)))
(end-of-line)
(insert "\n\n" newitem " ")))
+;; FIXME: Isn't this a `defconst'?
(defvar rst-initial-enums
(let (vals)
(dolist (fmt '("%s." "(%s)" "%s)"))
(cons "#." (nreverse vals)))
"List of initial enumerations.")
+;; FIXME: Isn't this a `defconst'?
(defvar rst-initial-items
(append (mapcar 'char-to-string rst-bullets) rst-initial-enums)
"List of initial items. It's collection of bullets and enumerations.")
:package-version '(rst . "1.1.0"))
(define-obsolete-variable-alias
- 'rst-shift-basic-offset 'rst-indent-width "r6713")
+ 'rst-shift-basic-offset 'rst-indent-width "1.0.0")
(defcustom rst-indent-width 2
"Indentation when there is no more indentation point given."
:group 'rst-indent
(save-match-data
(unless (looking-at (rst-re 'lin-end))
(back-to-indentation)
- ;; Current indendation is always the least likely tab.
+ ;; Current indentation is always the least likely tab.
(let ((tabs (list (list (point) 0 nil)))) ; (POINT OFFSET INNER)
;; Push inner tabs more likely to continue writing.
(cond
(< newcol innermost))))
(not (memq newcol tablist)))
(push newcol tablist))))
- (setq innermost (if (some 'identity
- (mapcar 'cdr tabs)) ; Has inner.
+ (setq innermost (if (rst-some (mapcar 'cdr tabs)) ; Has inner.
leftcol
innermost))
(setq leftmost leftcol)))))
(cur (current-indentation))
(clm (current-column))
(tabs (rst-compute-tabs (point)))
- (fnd (position cur tabs))
+ (fnd (rst-position cur tabs))
ind)
(if (and (not tabs) (not dflt))
'noindent
(let* ((cmp (if (> cnt 0) '> '<))
(tabs (if (> cnt 0) tabs (reverse tabs)))
(len (length tabs))
- (dir (signum cnt)) ; Direction to take.
+ (dir (rst-signum cnt)) ; Direction to take.
(abs (abs cnt)) ; Absolute number of steps to take.
;; Get the position of the first tab beyond leftmostcol.
- (fnd (position-if (lambda (elt)
- (funcall cmp elt leftmostcol))
- tabs))
+ (fnd (lexical-let ((cmp cmp)
+ (leftmostcol leftmostcol)) ; Create closure.
+ (rst-position-if (lambda (elt)
+ (funcall cmp elt leftmostcol))
+ tabs)))
;; Virtual position of tab.
(pos (+ (or fnd len) (1- abs)))
(tab (if (< pos len)
;; FIXME: The obsolete variables need to disappear.
+;; The following versions have been done inside Emacs and should not be
+;; replaced by `:package-version' attributes until a change.
+
(defgroup rst-faces nil "Faces used in Rst Mode."
:group 'rst
:group 'faces
"customize the face `rst-reference' instead."
"24.1")
+(defface rst-transition '((t :inherit font-lock-keyword-face))
+ "Face used for a transition."
+ :package-version '(rst . "1.3.0")
+ :group 'rst-faces)
+
+(defface rst-adornment '((t :inherit font-lock-keyword-face))
+ "Face used for the adornment of a section header."
+ :package-version '(rst . "1.3.0")
+ :group 'rst-faces)
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; FIXME LEVEL-FACE: May be this complicated mechanism should be replaced
+;; simply by a number of customizable faces `rst-header-%d'
+;; which by default are set properly for dark and light
+;; background. Initialization should come from the old
+;; variables if they exist. A maximum level of 6 should
+;; suffice - after that the last level should be repeated.
+;; Only `rst-adornment-faces-alist' is needed outside this
+;; block. Would also fix docutils-Bugs-3479594.
+
(defgroup rst-faces-defaults nil
"Values used to generate default faces for section titles on all levels.
Tweak these if you are content with how section title faces are built in
(rst-define-level-faces)))
;; Faces for displaying items on several levels. These definitions define
-;; different shades of gray where the lightest one (i.e. least contrasting) is
-;; used for level 1.
+;; different shades of gray where the lightest one (i.e. least contrasting on a
+;; light background) is used for level 1.
(defcustom rst-level-face-max 6
"Maximum depth of levels for which section title faces are defined."
:group 'rst-faces-defaults
:type '(integer)
:set 'rst-set-level-default)
+;; FIXME: It should be possible to give "#RRGGBB" type of color values.
+;; Together with a `rst-level-face-end-light' this could be used for
+;; computing steps.
+;; FIXME: This variable should be combined with `rst-level-face-format-light'
+;; to a single string.
(defcustom rst-level-face-base-color "grey"
"Base name of the color for creating background colors in section title faces."
:group 'rst-faces-defaults
:type '(string)
:set 'rst-set-level-default)
+;; FIXME LEVEL-FACE: This needs to be done differently: The faces must specify
+;; how they behave for dark and light background using the
+;; relevant options explained in `defface'.
(defcustom rst-level-face-base-light
(if (eq frame-background-mode 'dark)
15
:group 'rst-faces-defaults
:type '(string)
:set 'rst-set-level-default)
+;; FIXME LEVEL-FACE: This needs to be done differently: The faces must specify
+;; how they behave for dark and light background using the
+;; relevant options explained in `defface'.
+;; FIXME: Alternatively there could be a customizable variable
+;; `rst-level-face-end-light' which defines the end value and steps are
+;; computed
(defcustom rst-level-face-step-light
(if (eq frame-background-mode 'dark)
7
:set 'rst-set-level-default)
(defcustom rst-adornment-faces-alist
- (let ((alist '((t . font-lock-keyword-face)
- (nil . font-lock-keyword-face)))
+ ;; FIXME LEVEL-FACE: Must be redone if `rst-level-face-max' is changed
+ (let ((alist (copy-sequence '((t . rst-transition)
+ (nil . rst-adornment))))
(i 1))
(while (<= i rst-level-face-max)
+ ;; FIXME: why not `push'?
(nconc alist (list (cons i (intern (format "rst-level-%d-face" i)))))
(setq i (1+ i)))
alist)
"Faces for the various adornment types.
-Key is a number (for the section title text of that level),
-t (for transitions) or nil (for section title adornment).
-If you generally do not like how section title text faces are
-set up tweak here. If the general idea is ok for you but you do not like the
-details check the Rst Faces Defaults group."
+Key is a number (for the section title text of that level
+starting with 1), t (for transitions) or nil (for section title
+adornment). If you generally do not like how section title text
+faces are set up tweak here. If the general idea is ok for you
+but you do not like the details check the Rst Faces Defaults
+group."
:group 'rst-faces
:type '(alist
:key-type
(choice
- (integer
- :tag
- "Section level (may not be bigger than `rst-level-face-max')")
- (boolean :tag "transitions (on) / section title adornment (off)"))
+ (integer :tag "Section level")
+ (const :tag "transitions" t)
+ (const :tag "section title adornment" nil))
:value-type (face))
:set-after '(rst-level-face-max))
-;; FIXME: It should be possible to give "#RRGGBB" type of color values.
(defun rst-define-level-faces ()
"Define the faces for the section title text faces from the values."
;; All variables used here must be checked in `rst-set-level-default'.
(let ((i 1))
(while (<= i rst-level-face-max)
(let ((sym (intern (format "rst-level-%d-face" i)))
- (doc (format "Face for showing section title text at level %d" i))
+ (doc (format "Default face for showing section title text at level %d.
+This symbol is *not* meant for customization but modified if a
+variable of the `rst-faces-defaults' group is customized. Use
+`rst-adornment-faces-alist' for customization instead." i))
(col (format (concat "%s" rst-level-face-format-light)
rst-level-face-base-color
(+ (* (1- i) rst-level-face-step-light)
rst-level-face-base-light))))
- (unless (facep sym)
- (make-empty-face sym)
- (set-face-doc-string sym doc)
- (set-face-background sym col)
- (set sym sym))
+ (make-empty-face sym)
+ (set-face-doc-string sym doc)
+ (set-face-background sym col)
+ (set sym sym)
(setq i (1+ i))))))
+;; FIXME LEVEL-FACE: This is probably superfluous since it is done by the
+;; customization / `rst-set-level-default'.
(rst-define-level-faces)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(if (bolp)
moved
(forward-line 0)
- (- moved (signum n)))))
+ (- moved (rst-signum n)))))
+;; FIXME: If a single line is made a section header by `rst-adjust' the header
+;; is not always fontified immediately.
(defun rst-font-lock-extend-region-extend (pt dir)
"Extend the region starting at point PT and extending in direction DIR.
Return extended point or nil if not moved."
(let* ((hier (rst-get-hierarchy))
(char (car key))
(style (cdr key)))
- (1+ (or (position-if (lambda (elt)
- (and (equal (car elt) char)
- (equal (cadr elt) style))) hier)
+ (1+ (or (lexical-let ((char char)
+ (style style)
+ (hier hier)) ; Create closure.
+ (rst-position-if (lambda (elt)
+ (and (equal (car elt) char)
+ (equal (cadr elt) style))) hier))
(length hier))))))
(defvar rst-font-lock-adornment-match nil
extension of produced filename, options to the tool (nil or a
string)) to be used for converting the document."
;; FIXME: These are not options but symbols which may be referenced by
- ;; `rst-compile-*-toolset` below.
+ ;; `rst-compile-*-toolset` below. The `:validate' keyword of
+ ;; `defcustom' may help to define this properly in newer Emacs
+ ;; versions (> 23.1).
:type '(alist :options (html latex newlatex pseudoxml xml pdf s5)
:key-type symbol
:value-type (list :tag "Specification"
(const :tag "No options" nil)
(string :tag "Options"))))
:group 'rst
- :version "24.1")
+ :package-version "1.2.0")
;; FIXME: Must be `defcustom`.
(defvar rst-compile-primary-toolset 'html
(defun rst-join-paragraph ()
"Join lines in current paragraph into one line, removing end-of-lines."
(interactive)
- (let ((fill-column 65000)) ; some big number.
+ (let ((fill-column 65000)) ; Some big number.
(call-interactively 'fill-paragraph)))
;; FIXME: Unbound command - should be bound or removed.
(t mark-active)))
\f
-(provide 'rst)
;; LocalWords: docutils http sourceforge rst html wp svn svnroot txt reST regex
;; LocalWords: regexes alist seq alt grp keymap abbrev overline overlines toc
-;; LocalWords: XML PNT propertized referencable
+;; LocalWords: XML PNT propertized
;; Local Variables:
;; sentence-end-double-space: t
;; End:
-;;; rst.el ends here.
+(provide 'rst)
+
+;;; rst.el ends here