From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Stefan Monnier Newsgroups: gmane.emacs.devel Subject: Re: Add a functionality of bullet list and enumeration list to rst.el. Date: Wed, 17 Nov 2010 17:30:46 -0500 Message-ID: References: <49423E47.9030503@gmail.com> NNTP-Posting-Host: lo.gmane.org Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" X-Trace: dough.gmane.org 1290110308 15054 80.91.229.12 (18 Nov 2010 19:58:28 GMT) X-Complaints-To: usenet@dough.gmane.org NNTP-Posting-Date: Thu, 18 Nov 2010 19:58:28 +0000 (UTC) Cc: emacs-devel@gnu.org To: Martin Blais , Stefan Merten , David Goodger , Weiwei Guo Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Thu Nov 18 20:58:22 2010 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([199.232.76.165]) by lo.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1PJAcf-0007qO-TS for ged-emacs-devel@m.gmane.org; Thu, 18 Nov 2010 20:58:22 +0100 Original-Received: from localhost ([127.0.0.1]:44775 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1PJAce-0000P1-Rs for ged-emacs-devel@m.gmane.org; Thu, 18 Nov 2010 14:58:20 -0500 Original-Received: from [140.186.70.92] (port=50476 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1PJAb1-0007sa-Qg for emacs-devel@gnu.org; Thu, 18 Nov 2010 14:56:42 -0500 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1PJAaz-0004d1-GB for emacs-devel@gnu.org; Thu, 18 Nov 2010 14:56:39 -0500 Original-Received: from pruche.dit.umontreal.ca ([132.204.246.22]:60413) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1PJAaz-0004ck-9Z for emacs-devel@gnu.org; Thu, 18 Nov 2010 14:56:37 -0500 Original-Received: from pastel.home (lechon.iro.umontreal.ca [132.204.27.242]) by pruche.dit.umontreal.ca (8.14.1/8.14.1) with ESMTP id oAIJuSl6006678; Thu, 18 Nov 2010 14:56:28 -0500 Original-Received: by pastel.home (Postfix, from userid 20848) id EA38DA82CC; Wed, 17 Nov 2010 17:30:46 -0500 (EST) In-Reply-To: <49423E47.9030503@gmail.com> (Weiwei Guo's message of "Fri, 12 Dec 2008 18:34:47 +0800") User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/24.0.50 (gnu/linux) X-NAI-Spam-Score: 0.5 X-NAI-Spam-Rules: 2 Rules triggered DATE_IN_PAST_12_24=0.5, RV3683=0 X-NAI-Spam-Level: X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6 (newer, 3) X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.devel:132829 Archived-At: --=-=-= Content-Type: text/plain Hello rst.el maintainers. Weiwei Guo submitted a patch to rst.el to improve the handling of enumerated items. It seems OK to me, but since I don't use rst.el my judgment might not be very relevant. Could you confirm that we should install it? I have included the original patch as well as an alternative patch which includes additional (untested) changes I made to improve the coding style (and fix an apparent bug in his patch w.r.t handling rst-re-items). Stefan --=-=-= Content-Type: text/x-diff Content-Disposition: inline; filename=rst-1.diff === modified file 'lisp/textmodes/rst.el' --- lisp/textmodes/rst.el 2010-10-03 02:26:35 +0000 +++ lisp/textmodes/rst.el 2010-11-17 22:28:22 +0000 @@ -36,6 +36,8 @@ ;; from it; ;; - Functions to insert and automatically update a TOC in your source ;; document; +;; - Function to insert list, processing item bullets and enumerations +;; automatically; ;; - Font-lock highlighting of notable reStructuredText structures; ;; - Some other convenience functions. ;; @@ -166,11 +168,6 @@ ;; - numbering: automatically detect if we have a section-numbering directive in ;; the corresponding section, to render the toc. ;; -;; bulleted and enumerated list items -;; ---------------------------------- -;; - We need to provide way to rebullet bulleted lists, and that would include -;; automatic enumeration as well. -;; ;; Other ;; ----- ;; - It would be nice to differentiate between text files using @@ -260,6 +257,8 @@ ;; ;; Operating on Blocks of Text. ;; + ;; Inserts bullet list or enumeration list. + (define-key map [(meta return)] 'rst-insert-list) ;; Makes paragraphs in region as a bullet list. (define-key map [(control c) (control b)] 'rst-bullet-list-region) ;; Makes paragraphs in region as a enumeration. @@ -1506,6 +1505,62 @@ ) ))) +;================================================= +; Borrowed from a2r.el (version 1.3), writen by Lawrence Mitchell +; I need to make some tiny changes on the functions, so I put it here. +; -- Wei-Wei Guo + +(defconst arabic-to-roman + '((1000 . "M") (900 . "CM") (500 . "D") (400 . "CD") + (100 . "C") (90 . "XC") (50 . "L") (40 . "XL") + (10 . "X") (9 . "IX") (5 . "V") (4 . "IV") + (1 . "I")) + "List of maps between Arabic numbers and their Roman numeral equivalents.") + +(defun arabic-to-roman (num &optional arg) + "Convert Arabic number NUM to its Roman numeral representation. + +Obviously, NUM must be greater than zero. Don't blame me, blame the +Romans, I mean \"what have the Romans ever _done_ for /us/?\" (with +apologies to Monty Python). +If optional prefix ARG is non-nil, insert in current buffer." + (let ((map arabic-to-roman) + res) + (while (and map (> num 0)) + (if (or (= num (caar map)) + (> num (caar map))) + (setq res (concat res (cdar map)) + num (- num (caar map))) + (setq map (cdr map)))) + res)) + +(defconst roman-to-arabic + '(("M" . 1000) ("CM" . 900) ("D" . 500) ("CD" . 400) + ("C" . 100) ("XC" . 90) ("L" . 50) ("XL" . 40) + ("X" . 10) ("IX" . 9) ("V" . 5) ("IV" . 4) + ("I" . 1)) + "List of maps between Roman numerals and their Arabic equivalents.") + +(defun roman-to-arabic (string &optional arg) + "Convert STRING of Roman numerals to an Arabic number. + +If STRING contains a letter which isn't a valid Roman numeral, the rest +of the string from that point onwards is ignored. + +Hence: +MMD == 2500 +and +MMDFLXXVI == 2500. +If optional ARG is non-nil, insert in current buffer." + (let ((res 0) + (map roman-to-arabic)) + (while map + (if (string-match (concat "^" (caar map)) string) + (setq res (+ res (cdar map)) + string (replace-match "" nil t string)) + (setq map (cdr map)))) + res)) +;================================================= (defun rst-find-pfx-in-region (beg end pfx-re) "Find all the positions of prefixes in region between BEG and END. @@ -1531,23 +1586,231 @@ (forward-line 1)) ) (nreverse pfx))) +(defun rst-indent-return () + "Add a new line at blank line with indent keeped." + (interactive) + (when (save-excursion + (beginning-of-line) + (looking-at "^[ \t]*$")) + (beginning-of-line) + (insert "\n") + (end-of-line))) + +(defun rst-insert-list-pos (newitem) + "Arrage relative position of a newly inserted list item. + +Adding a new list might consider three situations: + + (a) Current line is a blank line. + (b) Previous line is a blank line. + (c) Following line is a blank line. + +When (a) and (b), just add the new list at current line. + +when (a) and not (b), a blank line is added before adding the new list. + +When not (a), first forward point to the end of the line, and add two +blank lines, then add the new list. + +Other situations are just ignored and left to users themselves." + (if (save-excursion + (beginning-of-line) + (looking-at "^[ \t]*$")) + (if (save-excursion + (forward-line -1) + (looking-at "^[ \t]*$")) + (insert (concat newitem " ")) + (insert (concat "\n" newitem " "))) + (progn + (end-of-line) + (insert (concat "\n\n" newitem " "))))) + +(defvar rst-initial-enums + '("#." "1." "a." "A." "I." "i." "(1)" "(a)" "(A)" "(I)" "(i)" "1)" "a)" "A)" "I)" "i)") + "List of initial enumerates.") + +(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") + +(defun rst-insert-list-new-item () + "Insert a new list item. + +User is asked to select the item style first, for example (a), i), +. Use TAB +for completition and choices. + +If user selects bullets or #, it's just added with position arranged by +`rst-insert-list-new-pos'. + +If user selects enumerates, a further prompt is given. User need to input a +starting item, for example 'e' for 'A)' style. The position is also arranged by +`rst-insert-list-new-pos'. +" + (interactive) + (let (itemstyle itemno itemfirst) + (setq itemstyle (completing-read "Providing perfered item (default '#.'): " + rst-initial-items nil t nil nil "#.")) + (when (string-match "[aA1Ii]" itemstyle) + (setq itemfirst (match-string 0 itemstyle)) + (cond ((equal itemfirst "a") + (progn + (setq itemno (read-string "Providing starting (default a): " nil nil "a")) + (setq itemstyle (replace-match + (downcase itemno) + nil nil itemstyle)))) + ((equal itemfirst "A") + (progn + (setq itemno (read-string "Providing starting (default A): " nil nil "A")) + (setq itemstyle (replace-match + (upcase itemno) + nil nil itemstyle)))) + ((equal itemfirst "I") + (progn + (setq itemno (read-number "Providing starting (default 1): " 1)) + (string-match "[aA1Ii]" itemstyle) + (setq itemstyle (replace-match + (arabic-to-roman itemno) + nil nil itemstyle)))) + ((equal itemfirst "i") + (progn + (setq itemno (read-number "Providing starting (default 1): " 1)) + (string-match "[aA1Ii]" itemstyle) + (setq itemstyle (replace-match + (downcase (arabic-to-roman itemno)) + nil nil itemstyle)))) + ((equal itemfirst "1") + (progn + (setq itemno (read-number "Providing starting (default 1): " 1)) + (string-match "[aA1Ii]" itemstyle) + (setq itemstyle (replace-match + (number-to-string itemno) + nil nil itemstyle)))) + )) + (rst-insert-list-pos itemstyle))) + (defvar rst-re-bullets (format "\\([%s][ \t]\\)[^ \t]" (regexp-quote (concat rst-bullets))) "Regexp for finding bullets.") -;; (defvar rst-re-enumerations -;; "\\(\\(#\\|[0-9]+\\)\\.[ \t]\\)[^ \t]" -;; "Regexp for finding bullets.") +(defvar rst-re-enumerates + (format "^[ \t]*\\(%s\\|%s\\)[ \t]" + "\\([0-9]+\\|[a-zA-Z]\\|[IVXLCDMivxlcdm]+\\)\\." + "(?\\([0-9]+\\|[a-zA-Z]\\|[IVXLCDMivxlcdm]+\\))") + "Regexp for finding enumerates (# is not included).") (defvar rst-re-items - (format "\\(%s\\|%s\\)[^ \t]" - (format "[%s][ \t]" (regexp-quote (concat rst-bullets))) - "\\(#\\|[0-9]+\\)\\.[ \t]") - "Regexp for finding bullets.") + (format "^[ \t]*\\(%s\\|%s\\|%s\\)[ \t]" + (format "[%s]" (regexp-quote (concat rst-bullets))) + "\\(#\\|[a-z]\\|[0-9]+\\|[A-Z]\\|[IVXLCDM]+\\|[ivxlcdm]+\\)\\." + "(?\\([a-z]\\|[0-9]+\\|[A-Z]\\|[IVXLCDM]+\\|[ivxlcdm]+\\))") + "Regexp for finding bullets and enumerates.") -(defvar rst-preferred-bullets - '(?- ?* ?+) - "List of favourite bullets to set for straightening bullets.") +(defun rst-list-match-string (reg) + "Match a regex in a line and return the matched string by match-string. + +If nothing matched, a empty string is returned." + (let (matched) + (save-excursion + (end-of-line) + (if (re-search-backward reg (line-beginning-position) t) + (setq matched (match-string 0)) + (setq matched ""))) + matched)) + +(defun rst-insert-list-continue () + "Insert a list item with current list style and indentation level. + +The function works for all style of bullet lists and enumeration lists. Only one +thing need to be noticed: + +List style alphabetical list, such as 'a.', and roman numerical list, such as 'i.', +have some overlapping items, for example 'v.' The function can deal with the +problem elegantly in most situations. But when those overlapped list proceeded +by a blank line, it is hard to determine which type to use automatically. The +function uses roman numerical list defaultly. If you want alphabetical list, just +use a prefix (\\[universal-argument]). +" + (interactive) + (let (curitem newitem itemno previtem tmpitem) + (setq curitem (rst-list-match-string rst-re-items)) + (cond ((string-match (format "#.\\|[%s]" + (regexp-quote (concat rst-bullets))) curitem) + (setq newitem curitem)) + ((string-match "[0-9]+" curitem) + (progn + (setq itemno (1+ + (string-to-number + (match-string 0 curitem)))) + (setq newitem (replace-match + (number-to-string itemno) + nil nil curitem)))) + ((and (string-match "[IVXLCDMivxlcdm]+" curitem) + (progn + (setq tmpitem (match-string 0 curitem)) + (or (> (length tmpitem) 1) + (and (= (length tmpitem) 1) + (null current-prefix-arg) + (progn + (save-excursion + (forward-line -1) + (setq previtem (rst-list-match-string rst-re-enumerates)) + (when (string-match "[a-zA-Z]+" previtem) + (setq previtem (match-string 0 previtem)))) + (or (> (length previtem) 1) + (= (length previtem) 0))))))) + (progn + (setq itemno (1+ (roman-to-arabic tmpitem))) + (string-match "[IVXLCDMivxlcdm]+" curitem) + (if (isearch-no-upper-case-p tmpitem nil) + (setq newitem (replace-match + (downcase (arabic-to-roman itemno)) + nil nil curitem)) + (setq newitem (replace-match + (arabic-to-roman itemno) + nil nil curitem))))) + ((string-match "[a-zA-Z]" curitem) + (progn + (setq itemno (1+ + (string-to-char + (match-string 0 curitem)))) + (setq newitem (replace-match + (char-to-string itemno) + nil nil curitem))))) + (insert (concat "\n" newitem)))) + + +(defun rst-insert-list () + "Insert a list item at the current point. + +The command can insert a new list or a continuing list. When it is called at a +non-list line, it will promote to insert new list. When it is called at a list +line, it will insert a list with the same list style. + +1. When inserting a new list: + +User is asked to select the item style first, for example (a), i), +. Use TAB +for completition and choices. + + (a) If user selects bullets or #, it's just added. + (b) If user selects enumerates, a further prompt is given. User need to input a +starting item, for example 'e' for 'A)' style. + +The position of the new list is arranged according whether or not the current line +and the previous line are blank lines. + +2. When continuing a list, one thing need to be noticed: + +List style alphabetical list, such as 'a.', and roman numerical list, such as 'i.', +have some overlapping items, for example 'v.' The function can deal with the +problem elegantly in most situations. But when those overlapped list proceeded +by a blank line, it is hard to determine which type to use automatically. The +function uses roman numerical list defaultly. If you want alphabetical list, just +use a prefix (\\[universal-argument]). +" + (interactive) + (if (equal (rst-list-match-string rst-re-items) "") + (rst-insert-list-new-item) + (rst-insert-list-continue))) (defun rst-straighten-bullets-region (beg end) "Make all the bulleted list items in the region consistent. @@ -1555,9 +1818,9 @@ after you have merged multiple bulleted lists to make them use the same/correct/consistent bullet characters. -See variable `rst-preferred-bullets' for the list of bullets to -adjust. If bullets are found on levels beyond the -`rst-preferred-bullets' list, they are not modified." +See variable `rst-bullets' for the list of bullets to adjust. +If bullets are found on levels beyond the `rst-bullets' list, +they are not modified." (interactive "r") (let ((bullets (rst-find-pfx-in-region beg end @@ -1576,7 +1839,7 @@ (let ((poslist ())) ; List of (indent . positions). (maphash (lambda (x y) (push (cons x y) poslist)) levtable) - (let ((bullets rst-preferred-bullets)) + (let ((bullets rst-bullets)) (dolist (x (sort poslist 'car-less-than-car)) (when bullets ;; Apply the characters. --=-=-= Content-Type: text/x-diff Content-Disposition: inline; filename=rst-2.diff === modified file 'lisp/textmodes/rst.el' --- lisp/textmodes/rst.el 2010-10-03 02:26:35 +0000 +++ lisp/textmodes/rst.el 2010-11-17 22:11:18 +0000 @@ -36,6 +36,8 @@ ;; from it; ;; - Functions to insert and automatically update a TOC in your source ;; document; +;; - Function to insert list, processing item bullets and enumerations +;; automatically; ;; - Font-lock highlighting of notable reStructuredText structures; ;; - Some other convenience functions. ;; @@ -166,11 +168,6 @@ ;; - numbering: automatically detect if we have a section-numbering directive in ;; the corresponding section, to render the toc. ;; -;; bulleted and enumerated list items -;; ---------------------------------- -;; - We need to provide way to rebullet bulleted lists, and that would include -;; automatic enumeration as well. -;; ;; Other ;; ----- ;; - It would be nice to differentiate between text files using @@ -260,6 +257,8 @@ ;; ;; Operating on Blocks of Text. ;; + ;; Inserts bullet list or enumeration list. + (define-key map [?\M-\r] 'rst-insert-list) ;; Makes paragraphs in region as a bullet list. (define-key map [(control c) (control b)] 'rst-bullet-list-region) ;; Makes paragraphs in region as a enumeration. @@ -1506,6 +1505,55 @@ ) ))) +;================================================= +; Borrowed from a2r.el (version 1.3), by Lawrence Mitchell +; I needed to make some tiny changes to the functions, so I put it here. +; -- Wei-Wei Guo + +(defconst rst-arabic-to-roman + '((1000 . "M") (900 . "CM") (500 . "D") (400 . "CD") + (100 . "C") (90 . "XC") (50 . "L") (40 . "XL") + (10 . "X") (9 . "IX") (5 . "V") (4 . "IV") + (1 . "I")) + "List of maps between Arabic numbers and their Roman numeral equivalents.") + +(defun rst-arabic-to-roman (num &optional arg) + "Convert Arabic number NUM to its Roman numeral representation. + +Obviously, NUM must be greater than zero. Don't blame me, blame the +Romans, I mean \"what have the Romans ever _done_ for /us/?\" (with +apologies to Monty Python). +If optional prefix ARG is non-nil, insert in current buffer." + (let ((map rst-arabic-to-roman) + res) + (while (and map (> num 0)) + (if (or (= num (caar map)) + (> num (caar map))) + (setq res (concat res (cdar map)) + num (- num (caar map))) + (setq map (cdr map)))) + res)) + +(defun rst-roman-to-arabic (string &optional arg) + "Convert STRING of Roman numerals to an Arabic number. + +If STRING contains a letter which isn't a valid Roman numeral, the rest +of the string from that point onwards is ignored. + +Hence: +MMD == 2500 +and +MMDFLXXVI == 2500. +If optional ARG is non-nil, insert in current buffer." + (let ((res 0) + (map rst-arabic-to-roman)) + (while map + (if (string-match (concat "^" (cdar map)) string) + (setq res (+ res (caar map)) + string (replace-match "" nil t string)) + (setq map (cdr map)))) + res)) +;================================================= (defun rst-find-pfx-in-region (beg end pfx-re) "Find all the positions of prefixes in region between BEG and END. @@ -1531,24 +1579,203 @@ (forward-line 1)) ) (nreverse pfx))) +(defun rst-insert-list-pos (newitem) + "Arrange relative position of a newly inserted list item. + +Adding a new list might consider three situations: + + (a) Current line is a blank line. + (b) Previous line is a blank line. + (c) Following line is a blank line. + +When (a) and (b), just add the new list at current line. + +when (a) and not (b), a blank line is added before adding the new list. + +When not (a), first forward point to the end of the line, and add two +blank lines, then add the new list. + +Other situations are just ignored and left to users themselves." + (if (save-excursion + (beginning-of-line) + (looking-at "^[ \t]*$")) + (if (save-excursion + (forward-line -1) + (looking-at "^[ \t]*$")) + (insert newitem " ") + (insert "\n" newitem " ")) + (progn + (end-of-line) + (insert (concat "\n\n" newitem " "))))) + +(defvar rst-initial-enums + (let ((vals ())) + (dolist (fmt '("%s." "(%s)" "%s)")) + (dolist (c '("1" "a" "A" "I" "i")) + (push (format fmt c) vals))) + (cons "#." (nreverse vals))) + "List of initial enumerations.") + +(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.") + +(defun rst-insert-list-new-item () + "Insert a new list item. + +User is asked to select the item style first, for example (a), i), +. Use TAB +for completition and choices. + +If user selects bullets or #, it's just added with position arranged by +`rst-insert-list-pos'. + +If user selects enumerations, a further prompt is given. User need to input a +starting item, for example 'e' for 'A)' style. The position is also arranged by +`rst-insert-list-pos'." + (interactive) + (let ((itemstyle (completing-read "Providing perfered item (default '#.'): " + rst-initial-items nil t nil nil "#."))) + (rst-insert-list-pos + (case (aref itemstyle 0) + (?a + (let ((itemno (read-string "Providing starting (default a): " + nil nil "a"))) + (concat (downcase itemno) (substring itemstyle 1)))) + (?A + (let ((itemno (read-string "Providing starting (default A): " + nil nil "A"))) + (concat (upcase itemno) (substring itemstyle 1)))) + (?I + (let ((itemno (read-number "Providing starting (default 1): " 1))) + (concat (rst-arabic-to-roman itemno) (substring itemstyle 1)))) + (?i + (let ((itemno (read-number "Providing starting (default 1): " 1))) + (concat (downcase (rst-arabic-to-roman itemno)) + (substring itemstyle 1)))) + (?1 + (let ((itemno (read-number "Providing starting (default 1): " 1))) + (concat (number-to-string itemno) (substring itemstyle 1)))) + (t itemstyle))))) + (defvar rst-re-bullets (format "\\([%s][ \t]\\)[^ \t]" (regexp-quote (concat rst-bullets))) "Regexp for finding bullets.") -;; (defvar rst-re-enumerations -;; "\\(\\(#\\|[0-9]+\\)\\.[ \t]\\)[^ \t]" -;; "Regexp for finding bullets.") +(defconst rst-re-enumerator "\\(?:[a-zA-Z]\\|[0-9IVXLCDMivxlcdm]+\\)") + +(defvar rst-re-enumerations + (format "^[ \t]*\\(%s.\\|(?%s)\\)[ \t]" + rst-re-enumerator + rst-re-enumerator) + "Regexp for finding enumerations (# is not included).") (defvar rst-re-items - (format "\\(%s\\|%s\\)[^ \t]" - (format "[%s][ \t]" (regexp-quote (concat rst-bullets))) - "\\(#\\|[0-9]+\\)\\.[ \t]") - "Regexp for finding bullets.") + (format "^[ \t]*\\([%s]\\|\\(#\\|%s\\)\\.\\|(?%s)\\)[ \t]" + (regexp-quote (concat rst-bullets)) + rst-re-enumerator + rst-re-enumerator) + "Regexp for finding bullets and enumerations.") (defvar rst-preferred-bullets '(?- ?* ?+) "List of favourite bullets to set for straightening bullets.") +(defun rst-list-match-string (reg) + "Match a regex in a line and return the matched string. +If nothing matched, an empty string is returned." + (save-excursion + (end-of-line) + (if (re-search-backward reg (line-beginning-position) t) + (match-string 0) + ""))) + +(defun rst-insert-list-continue () + "Insert a list item with current list style and indentation level. + +The function works for all style of bullet lists and enumeration lists. +Only one thing needs to be noticed: + +List style alphabetical list, such as 'a.', and roman numerical list, such as +'i.', have some overlapping items, for example 'v.' The function can deal with +the problem elegantly in most situations. But when those overlapped lists +are preceded by a blank line, it is hard to determine which type to use +automatically. The function uses roman numerical list by default. If you want +alphabetical list, just use a prefix (\\[universal-argument]). " + (interactive) + (let* ((curitem (rst-list-match-string rst-re-items)) + tmpitem) + (insert + "\n" + (cond ((string-match (format "#.\\|[%s]" + (regexp-quote (concat rst-bullets))) + curitem) + curitem) + ((string-match "[0-9]+" curitem) + (let ((itemno (1+ (string-to-number + (match-string 0 curitem))))) + (replace-match (number-to-string itemno) nil nil curitem))) + ((and (string-match "[IVXLCDMivxlcdm]+" curitem) + (progn + (setq tmpitem (match-string 0 curitem)) + (or (> (length tmpitem) 1) + (and (= (length tmpitem) 1) + (null current-prefix-arg) + (let ((previtem + (save-excursion + (forward-line -1) + (rst-list-match-string + rst-re-enumerations)))) + (when (string-match "[a-zA-Z]+" previtem) + (setq previtem (match-string 0 previtem))) + (or (> (length previtem) 1) + (= (length previtem) 0))))))) + (let ((itemno (1+ (rst-roman-to-arabic tmpitem)))) + (string-match "[IVXLCDMivxlcdm]+" curitem) + (if (isearch-no-upper-case-p tmpitem nil) + (replace-match + (downcase (rst-arabic-to-roman itemno)) + nil nil curitem) + (replace-match + (rst-arabic-to-roman itemno) + nil nil curitem)))) + ((string-match "[a-zA-Z]" curitem) + (let ((itemno (1+ (string-to-char + (match-string 0 curitem))))) + (replace-match (char-to-string itemno) nil nil curitem))))))) + + +(defun rst-insert-list () + "Insert a list item at the current point. + +The command can insert a new list or a continuing list. When it is called at a +non-list line, it will promote to insert new list. When it is called at a list +line, it will insert a list with the same list style. + +1. When inserting a new list: + +User is asked to select the item style first, for example (a), i), +. Use TAB +for completition and choices. + + (a) If user selects bullets or #, it's just added. + (b) If user selects enumerations, a further prompt is given. User needs to + input a starting item, for example 'e' for 'A)' style. + +The position of the new list is arranged according to whether or not the +current line and the previous line are blank lines. + +2. When continuing a list, one thing need to be noticed: + +List style alphabetical list, such as 'a.', and roman numerical list, such as +'i.', have some overlapping items, for example 'v.' The function can deal with +the problem elegantly in most situations. But when those overlapped list are +preceded by a blank line, it is hard to determine which type to use +automatically. The function uses roman numerical list by default. If you want +alphabetical list, just use a prefix (\\[universal-argument])." + (interactive) + (if (equal (rst-list-match-string rst-re-items) "") + (rst-insert-list-new-item) + (rst-insert-list-continue))) + (defun rst-straighten-bullets-region (beg end) "Make all the bulleted list items in the region consistent. The region is specified between BEG and END. You can use this @@ -2549,7 +2776,7 @@ (dolist (x items) (goto-char (car x)) (looking-at rst-re-items) - (replace-match (format "%d. " count) nil nil nil 1) + (replace-match (format "%d." count) nil nil nil 1) (incf count) )) )) --=-=-=--