emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Add a functionality of bullet list and enumeration list to rst.el.


From: Stefan Monnier
Subject: Re: Add a functionality of bullet list and enumeration list to rst.el.
Date: Wed, 17 Nov 2010 17:30:46 -0500
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/24.0.50 (gnu/linux)

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

=== 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 
<address@hidden>
+; 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.

=== 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 <address@hidden>
+; 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)
        ))
     ))


reply via email to

[Prev in Thread] Current Thread [Next in Thread]