Package: emacs;
Reported by: Weiwei Guo <wwguocn <at> gmail.com>
Date: Wed, 17 Dec 2008 19:45:03 UTC
Owned by: Stefan Merten <smerten <at> oekonux.de>
Severity: wishlist
Tags: confirmed
Done: Lars Ingebrigtsen <larsi <at> gnus.org>
Bug is archived. No further changes may be made.
View this message in rfc822 format
From: Stefan Monnier <monnier <at> iro.umontreal.ca> To: 1610 <at> debbugs.gnu.org Cc: Wei-Wei Guo <wwguocn <at> gmail.com> Subject: bug#1610: [Wei-Wei Guo] A patch for rst.el Date: Tue, 28 Apr 2009 10:32:34 -0400
[Message part 1 (text/plain, inline)]
tag 1610 +patch thanks
[Message part 2 (message/rfc822, inline)]
From: Wei-Wei Guo <wwguocn <at> gmail.com> To: emacs-devel <at> gnu.org Subject: A patch for rst.el Date: Tue, 28 Apr 2009 21:29:53 +0800[Message part 3 (text/plain, inline)]Dear all, I made a patch for rst.el, see the attachment. I sent a rst.el patch months ago and Glenn Morris filed it as a wishlist item: http://debbugs.gnu.org/cgi/bugreport.cgi?bug=1610 I promoted the functionalities recently so I send it here again. Added functionalities include: - Insert bullet list and enumeration by 'M-RET'. - Insert directives and options by 'C-c C-d'. - Insert option by 'C-c C-o'. - Insert hyperlink, footnote, and citation by 'C-c C-h'. - Jump within hyperlinks by 'C-c l', 'C-c n', and 'C-c t'. - jump within footnotes, and citation by 'C-c r', 'C-c m', and 'C-c u'. - Add your own directives by function 'rst-add-directives'. Hope it useful. Best wishes, Wei-Wei[rst.patch (text/plain, inline)]--- rst.el 2009-04-01 08:28:16.000000000 +0800 +++ rst.el.new 2009-04-28 17:36:38.000000000 +0800 @@ -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 @@ -239,14 +236,14 @@ ;; Section Decorations. ;; ;; The adjustment function that decorates or rotates a section title. - (define-key map [(control c) (control a)] 'rst-adjust) - (define-key map [(control c) (control ?=)] 'rst-adjust) + ;(define-key map [(control c) (control a)] 'rst-adjust) + ;(define-key map [(control c) (control ?=)] 'rst-adjust) (define-key map [(control ?=)] 'rst-adjust) ;; (Does not work on the Mac OSX.) ;; Display the hierarchy of decorations implied by the current document contents. - (define-key map [(control c) (control h)] 'rst-display-decorations-hierarchy) + (define-key map [(control c) (control t)] 'rst-display-decorations-hierarchy) ;; Homogeneize the decorations in the document. (define-key map [(control c) (control s)] 'rst-straighten-decorations) -;; (define-key map [(control c) (control s)] 'rst-straighten-deco-spacing) + ;(define-key map [(control c) (control s)] 'rst-straighten-deco-spacing) ;; ;; Section Movement and Selection. @@ -254,39 +251,75 @@ ;; Mark the subsection where the cursor is. (define-key map [(control c) (control m)] 'rst-mark-section) ;; Move forward/backward between section titles. - (define-key map [(control c) (control n)] 'rst-forward-section) - (define-key map [(control c) (control p)] 'rst-backward-section) + (define-key map [(meta n)] 'rst-forward-section) + (define-key map [(meta p)] 'rst-backward-section) ;; ;; Operating on Blocks of Text. ;; + ;; Inserts bullet list or enumeration list. + (define-key map [(meta return)] 'rst-insert-list) + ;; Inserts definition list. + ;(define-key map [(control c) t] 'rst-insert-definition) + ;; Inserts field list. + ;(define-key map [(control c) f] 'rst-insert-field) ;; Makes paragraphs in region as a bullet list. - (define-key map [(control c) (control b)] 'rst-bullet-list-region) + ;(define-key map [(control c) (control b)] 'rst-bullet-list-region) ;; Makes paragraphs in region as a enumeration. - (define-key map [(control c) (control e)] 'rst-enumerate-region) + ;(define-key map [(control c) (control e)] 'rst-enumerate-region) ;; Converts bullets to an enumeration. - (define-key map [(control c) (control v)] 'rst-convert-bullets-to-enumeration) + ;(define-key map [(control c) (control v)] 'rst-convert-bullets-to-enumeration) ;; Makes region a line-block. - (define-key map [(control c) (control d)] 'rst-line-block-region) + ;(define-key map [(control c) (control d)] 'rst-line-block-region) ;; Make sure that all the bullets in the region are consistent. - (define-key map [(control c) (control w)] 'rst-straighten-bullets-region) + ;(define-key map [(control c) (control w)] 'rst-straighten-bullets-region) ;; Shift region left or right (taking into account of enumerations/bullets, etc.). (define-key map [(control c) (control l)] 'rst-shift-region-left) (define-key map [(control c) (control r)] 'rst-shift-region-right) ;; Comment/uncomment the active region. - (define-key map [(control c) (control c)] 'comment-region) + ;(define-key map [(control c) (control c)] 'comment-region) + + ;; Insert option or directive. + (define-key map [(control c) (control o)] 'rst-insert-option) + (define-key map [(control c) (control d)] 'rst-insert-directive) + ;; Insert text replace definition. + ;(define-key map [(control c) t] 'rst-insert-replace) + ;; Insert image and figures + ;(define-key map [(control c) p] 'rst-insert-image) + ;(define-key map [(control c) m] 'rst-insert-figure) + ;; Insert admonition + ;(define-key map [(control c) t] 'rst-insert-admonition) + + ;; + ;; Hypylink, Footnote, and Citation Features. + ;; + (define-key map [(control c) (control h)] 'rst-insert-link) + ;; Insert hyperlink + ;(define-key map [(control c) l] 'rst-insert-inline-link) + ;; Insert footnote + ;(define-key map [(control c) f] 'rst-insert-footnote) + ;; Insert citation + ;(define-key map [(control c) c] 'rst-insert-citation) + ;; Hyperlink jumping + (define-key map [(control c) (l)] 'rst-link-jump-to-reference) + (define-key map [(control c) (n)] 'rst-link-jump-within-targets) + (define-key map [(control c) (t)] 'rst-link-jump-to-target) + ;; Footnote and citation jumping + (define-key map [(control c) (r)] 'rst-footnote-citation-jump-to-reference) + (define-key map [(control c) (m)] 'rst-footnote-citation-jump-within-targets) + (define-key map [(control c) (u)] 'rst-footnote-citation-jump-to-target) ;; ;; Table-of-Contents Features. ;; ;; Enter a TOC buffer to view and move to a specific section. (define-key map [(control c) (control t)] 'rst-toc) - ;; Insert a TOC here. - (define-key map [(control c) (control i)] 'rst-toc-insert) + ;; Insert a TOC here. use `rst-insert-directive' instead + ;(define-key map [(control c) i] 'rst-toc-insert) ;; Update the document's TOC (without changing the cursor position). (define-key map [(control c) (control u)] 'rst-toc-update) ;; Got to the section under the cursor (cursor must be in TOC). - (define-key map [(control c) (control f)] 'rst-goto-section) + ;(define-key map [(control c) (control f)] 'rst-goto-section) ;; ;; Converting Documents from Emacs. @@ -344,8 +377,8 @@ (defcustom rst-mode-hook nil - "Hook run when Rst mode is turned on. -The hook for Text mode is run before this one." + "Hook run when Rst Mode is turned on. +The hook for Text Mode is run before this one." :group 'rst :type '(hook)) @@ -1504,6 +1537,66 @@ ))) +;================================================= +; list related functions. + +;============== +; Borrowed from a2r.el (version 1.3), writen by Lawrence Mitchell <wence <at> gmx.li> +; 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. This is used to find bullets and enumerated list items. PFX-RE @@ -1528,23 +1621,221 @@ (forward-line 1)) ) (nreverse pfx))) +(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), add a blank line before adding the new list. + +When not (a), add a blank line and a new line at current point. + +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 + (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. @@ -1552,9 +1843,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 @@ -1573,7 +1864,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. @@ -1583,6 +1874,9 @@ (insert (string (car bullets)))) (setq bullets (cdr bullets)))))))) +;================================================= + + (defun rst-rstrip (str) "Strips the whitespace at the end of string STR." (string-match "[ \t\n]*\\'" str) @@ -1908,7 +2202,7 @@ (let ((p (point))) (save-excursion (when (rst-toc-insert-find-delete-contents) - (insert "\n ") + (insert "\n ") (rst-toc-insert) )) ;; Somehow save-excursion does not really work well. @@ -2816,7 +3110,7 @@ 1 rst-block-face) ;; `Enumerated Lists`_ (list - (concat re-bol "\\((?\\(#\\|[0-9]+\\|[A-Za-z]\\|[IVXLCMivxlcm]+\\)[.)]" + (concat re-bol "\\((?\\(#\\|[0-9]+\\|[A-Za-z]\\|[IVXLCDMivxlcdm]+\\)[.)]" re-blksep1 "\\)") 1 rst-block-face) ;; `Definition Lists`_ FIXME: missing @@ -3182,6 +3476,624 @@ (set-match-data mtc) t)))) + + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; directives and hyperlinks. + +;===== directive type list and command ===== + +(defvar rst-directive-type-alist + '(("definition" . rst-insert-definition) + ("field" . rst-insert-field) + ("admonition" . rst-insert-admonition) + ("image" . rst-insert-image) + ("figure" . rst-insert-figure) + ("topic" . rst-insert-topic) + ("sidebar" . rst-insert-sidebar) + ("line-block" . rst-insert-line-block) + ("parsed-literal" . rst-insert-parsed-literal) + ("rubric" . rst-insert-rubric) + ("epigraph" . rst-insert-epigraph) + ("highlights" . rst-insert-highlights) + ("pull-quote" . rst-insert-pull-quote) + ("compound" . rst-insert-compound) + ("container" . rst-insert-container) + ("table" . rst-insert-table) + ("csv-table" . rst-insert-csv-table) + ("list-table" . rst-insert-list-table) + ("contents" . rst-insert-contents) + ("sectnum" . rst-insert-sectnum) + ("replace" . rst-insert-replace) + ("unicode" . rst-insert-unicode) + ("date" . rst-insert-date) + ("include" . rst-insert-include) + ("raw" . rst-insert-raw)) + "List of directive inserting functions of directive types.") + +(defvar rst-directive-types + '("definition" "field" "admonition" + "image" "figure" + "topic" "sidebar" "line-block" "parsed-literal" "rubric" "epigraph" + "highlights" "pull-quote" "compound" "container" + "table" "csv-table" "list-table" + "contents" "sectnum" "include" "raw" + "replace" "unicode" "date" +) + "List of directive types") + +(defvar rst-directive-option-list + '(("definition" rst-option-definition t) + ("field" rst-option-field t) + ("admonition" rst-option-admonition nil) + ("image" rst-option-image nil) + ("figure" rst-option-figure t) + ("topic" nil t) + ("sidebar" rst-option-sidebar t) + ("line-block" nil t) + ("parsed-literal" nil t) + ("rubric" nil nil) + ("epigraph" nil t) + ("highlights" nil t) + ("pull-quote" nil t) + ("compound" nil t) + ("container" nil t) + ("table" nil t) + ("csv-table" rst-option-csv-table t) + ("list-table" rst-option-list-table t) + ("contents" rst-contents-option nil) + ("sectnum" rst-sectnum-option nil) + ("replace" nil nil) + ("unicode" rst-option-unicode nil) + ("date" nil nil) + ("include" rst-include-option nil) + ("raw" rst-option-raw t)) + "List of option functions of directive types.") + +(defun rst-add-directive-type (type directfunc optalist content) + "Adding new directive to directive alist and completion list. + +Use the following way to add directive type. + + (rst-add-directive-type \"definition\" + 'rst-insert-definition + 'rst-directive-options + 'content-presence-boolean) +" + (add-to-list 'rst-directive-types type) + (add-to-list 'rst-directive-type-alist (cons type directfunc)) + (add-to-list 'rst-directive-option-list (list type optalist content))) + +(defun rst-add-directives (directlist) + "Meta function of add directives. + +Elements of directives should arranged as + + (type funciton option-list content-boolean). +" + (dolist (direct directlist) + (eval (cons 'rst-add-directive-type direct)))) + +(defun rst-insert-directive () + "Meta-function of all directives." + (interactive) + (let (type optlist) + (setq type (completing-read "Providing directive type: " rst-directive-types)) + (funcall (cdr (assoc type rst-directive-type-alist))) + (setq optlist (eval (car (cdr (assoc type rst-directive-option-list))))) + (if optlist + (while (y-or-n-p "Set directive option(s)? ") + (rst-option-directive optlist))) + (if (eval (cadr (cdr (assoc type rst-directive-option-list)))) + (insert "\n ") + (newline)))) + +;==== directive and list definitions ==== + +;--- list looks like directive --- + +(defun rst-insert-definition () + "Insert a definition list" + (interactive) + (let (term classifiers classel) + (setq term (read-string "Providing the definition's term: ")) + (setq classifiers (read-string "Providing classifier(s) (if many, seperated by ', '): ")) + (if (equal classifiers "") + (insert term "\n ") + (progn + (setq classifiers (split-string classifiers ", ")) + (dolist (tmpclass classifiers) + (setq classel (concat classel " : " tmpclass))) + (insert term classel "\n "))))) + +(defun rst-insert-field () + "Insert a field list." + (interactive) + (let (field value) + (setq field (read-string "Providing field: ")) + (save-excursion + (beginning-of-line) + (insert (concat ":" field ": "))))) + +;--- function for defining directives --- + +(defun rst-insert-directive-type (type &optional argument) + "Insert the first line of directive" + (insert (concat ".. " type ":: " argument "\n"))) + +(defun rst-insert-directive-option (option &optional value) + "Insert an option line of directive" + (insert (concat " :" option ": " value "\n"))) + +(defun rst-insert-option () + "Insert a directive option." + (interactive) + (let (option value) + (save-excursion + (beginning-of-line) + (when (looking-at "^\\.\\. \\sw+::") + (setq option (read-string "Providing directive option: ")) + (setq value (read-string "Providing option value: ")) + (newline) + (rst-insert-directive-option option value))))) + +(defun rst-option-directive (optalist) + "Insert directive options in directive inserting function." + (let (optlist option type value) + (setq optlist (mapcar 'car optalist)) + (setq option (completing-read "Providing option: " optlist)) + (setq type (car (cdr (assoc option optalist)))) + (setq value + (cond + ((equal type "flag") nil) + ((equal type "option") (completing-read + "Providing optional value: " + (cadr (cdr (assoc option optalist))))) + ((equal type "number") (number-to-string + (read-number "Providing numeric value: "))) + ((equal type "string") (read-string "Providing value: ")))) + (rst-insert-directive-option option value))) + +;--- directives --- + +(defun rst-insert-admonition () + "Insert a admonition." + (interactive) + (let (admon argu) + (setq admon (read-string "Providing admonition type: ")) + (setq argu (read-string "Providing admonition description: ")) + (rst-insert-directive-type admon argu))) + +(defun rst-insert-image () + "Insert a image." + (interactive) + (let (arg) + (setq arg (read-string "Providing image and its path: ")) + (rst-insert-directive-type "image" arg))) + +(defvar rst-option-image +'(("align" "option" ("top" "middle" "bottom" "left" "center" "right")) + ("width" "number" 300) + ("height" "number" 300) + ("scale" "number" 80) + ("alt" "string" "") + ("target" "string" ""))) + +(defun rst-insert-figure () + "Insert a image." + (interactive) + (let (arg) + (setq arg (read-string "Providing figure and its path: ")) + (rst-insert-directive-type "figure" arg))) + +(defvar rst-option-figure +'(("align" "option" ("left" "center" "right")) + ("width" "number" 300) + ("height" "number" 300) + ("scale" "number" 80) + ("figwidth" "string" "350") + ("alt" "string" "") + ("target" "string" ""))) + +(defun rst-insert-topic () + "Insert a topic." + (interactive) + (let (arg) + (setq arg (read-string "Providing topic title: ")) + (rst-insert-directive-type "topic" arg))) + +(defun rst-insert-sidebar () + "Insert a sidebar." + (interactive) + (let (arg) + (setq arg (read-string "Providing sidebar title: ")) + (rst-insert-directive-type "sidebar" arg))) + +(defvar rst-option-sidebar +'(("subtitle" "string" ""))) + +(defun rst-insert-line-block () + "Insert a line block." + (interactive) + (rst-insert-directive-type "line-block")) + +(defun rst-insert-parsed-literal () + "Insert a parsed literal." + (interactive) + (rst-insert-directive-type "parsed-literal")) + +(defun rst-insert-rubric () + "Insert a rubric title." + (interactive) + (let (arg) + (setq arg (read-string "Providing rubric title: ")) + (rst-insert-directive-type "rubric" arg))) + +(defun rst-insert-epigraph () + "Insert a epigraph." + (interactive) + (rst-insert-directive-type "epigraph")) + +(defun rst-insert-highlights () + "Insert a highlights." + (interactive) + (rst-insert-directive-type "highlights")) + +(defun rst-insert-pull-quote () + "Insert a pull quote." + (interactive) + (rst-insert-directive-type "pull-quote")) + +(defun rst-insert-compound () + "Insert a compound." + (interactive) + (rst-insert-directive-type "compound")) + +(defun rst-insert-container () + "Insert a container." + (interactive) + (let (arg) + (setq arg (read-string "Providing container title: ")) + (rst-insert-directive-type "container" arg))) + +(defun rst-insert-table () + "Insert a table." + (interactive) + (let (arg) + (setq arg (read-string "Providing table title: ")) + (rst-insert-directive-type "table" arg))) + +(defun rst-insert-csv-table () + "Insert a table." + (interactive) + (let (arg) + (setq arg (read-string "Providing table title: ")) + (rst-insert-directive-type "csv-table" arg))) + +(defvar rst-option-csv-table +'(("widths" "string" "") + ("header-rows" "number" 0) + ("stub-columns" "number" 0) + ("header" "string" "") + ("file" "string" "") + ("url" "string" "") + ("encoding" "string" "") + ("delim" "string" "") + ("quote" "string" "") + ("keepspace" "flag" nil) + ("escape" "string" ""))) + +(defun rst-insert-list-table () + "Insert a table." + (interactive) + (let (arg) + (setq arg (read-string "Providing table title: ")) + (rst-insert-directive-type "list-table" arg))) + +(defvar rst-option-list-table +'(("widths" "string" "") + ("header-rows" "number" 0) + ("stub-columns" "number" 0))) + +(defun rst-insert-contents () + "Insert a contents." + (interactive) + (let (arg) + (setq arg (read-string "Providing contents title: ")) + (rst-insert-directive-type "contents" arg))) + +(defvar rst-option-contents +'(("backlinks" "option" ("entry" "top" "none")) + ("depth" "number" 2) + ("local" "flag" nil))) + +(defun rst-insert-sectnum () + "Set section-autonumbering." + (interactive) + (rst-insert-directive-type "sectnum")) + +(defvar rst-option-sectnum +'(("prefix" "string" "") + ("suffix" "string" "") + ("depth" "number" 2) + ("start" "number" 1))) + +(defun rst-insert-replace () + "Insert the head of word replace." + (interactive) + (let (tag) + (setq tag (read-string "Providing replaced word: ")) + (rst-insert-directive-type (concat "|" tag "| replace")))) + +(defun rst-insert-unicode () + "Insert unicode replacement." + (interactive) + (let (tag) + (setq tag (read-string "Providing unicode string: ")) + (rst-insert-directive-type (concat "|" tag "| unicode")))) + +(defvar rst-option-unicode + '(("ltrim" "flag" nil) + ("rtrim" "flag" nil) + ("trim" "flag" nil))) + +(defun rst-insert-date () + "Insert date or time." + (interactive) + (let (type value) + (setq type (completing-read "Insert date or time? " '("date" "time"))) + (cond + ((equal type "date") + (setq value (read-string "Providing date format: " nil nil "%Y-%m-%d"))) + ((equal type "time") + (setq value (read-string "Providing time format: " nil nil "%H:%M")))) + (rst-insert-directive-type (concat "|" type "| date") value))) + +(defun rst-insert-include () + "Insert an external file." + (interactive) + (let (arg) + (setq arg (read-string "Providing file path: ")) + (rst-insert-directive-type "include" arg))) + +(defvar rst-option-include + '(("start-after" "string" "") + ("end-before" "string" "") + ("encoding" "string" "") + ("literal" "flag" nil))) + +(defun rst-insert-raw () + "Insert raw data." + (interactive) + (let (arg) + (setq arg (read-string "Providing raw data type: ")) + (rst-insert-directive-type "raw" arg))) + +(defvar rst-option-raw + '(("file" "string" "") + ("url" "string" "") + ("encoding" "string" ""))) + + +;==== links ==== + +;--- link inserting --- + +(defvar rst-link-type-alist + '(("hyperlink" . rst-insert-inline-link) + ("footnote" . rst-insert-footnote) + ("citation" . rst-insert-citation)) + "List of link types.") + +(defvar rst-link-type + '("hyperlink" "footnote" "citation") + "List of link types for completion") + +(defun rst-insert-link () + "Meta-function of all directives." + (interactive) + (let (type) + (setq type (completing-read "Providing link type: " rst-link-type)) + (funcall (cdr (assoc type rst-link-type-alist))))) + +(defun rst-insert-inline-link () + "Insert a inline link with both target and reference." + (interactive) + (let (link target reference) + (setq link (read-string "Providing link name: ")) + (if (string-match " " link) + (progn + (setq target (concat "`" link "`_")) + (setq reference (concat ".. _`" link "`: "))) + (progn + (setq target (concat link "_")) + (setq reference (concat ".. _" link ": ")))) + (save-excursion + (if (equal (char-before) (string-to-char " ")) + (insert target " ") + (insert (concat " " target " "))) + (end-of-line) + (insert (concat "\n\n" reference))))) + +(defun rst-insert-footnote () + "Insert a inline footnote with both target and reference." + (interactive) + (let (footnote target reference) + (setq footnote (read-string "Providing footnote name: ")) + (setq target (concat "[#" footnote "]_")) + (setq reference (concat ".. [#" footnote "] ")) + (save-excursion + (if (equal (char-before) (string-to-char " ")) + (insert target " ") + (insert (concat " " target " "))) + (end-of-line) + (insert (concat "\n\n" reference))))) + +(defun rst-insert-citation () + "Insert a inline citation with both target and reference." + (interactive) + (let (citation target reference) + (setq citation (read-string "Providing citation name: ")) + (setq target (concat "[" citation "]_")) + (setq reference (concat ".. [" citation "] ")) + (save-excursion + (if (equal (char-before) (string-to-char " ")) + (insert target " ") + (insert (concat " " target " "))) + (end-of-line) + (insert (concat "\n\n" reference))))) + +;--- link jumping --- + +(defun rst-hyper-link-reference-match () + "Match link target around the point." + (let (link reference target) + (save-excursion + (if (search-forward "_" + (save-excursion + (forward-sentence) + (point)) + t 1) + (progn + (backward-char) + (unless (equal (char-before) ?\\) + (if (equal (char-before) ?`) + (progn + (forward-char) + (re-search-backward "`[[:alnum:][:punct:][:space:]]+`_" + (save-excursion + (search-backward "`" nil t 2) + (point)) + t) + (setq reference (match-string 0)) + (setq link (substring reference 0 -1))) + (progn + (forward-char) + (re-search-backward " \\sw+_" + (save-excursion + (search-backward " ") + (point)) + t) + (setq reference (match-string 0)) + (setq link (substring reference 1 -1))))) + (setq target (concat ".. _" link ":"))))) + (list reference target))) + +(defun rst-link-jump-to-target () + "Jump from intertext link reference to link target." + (interactive) + (let ((target (elt (rst-hyper-link-reference-match) 1))) + (when (save-excursion + (goto-char (point-min)) + (search-forward target)) + (goto-char (point-min)) + (search-forward target)))) + +(defun rst-link-jump-within-references () + "Jump within references of an intertext link, if exist." + (interactive) + (let ((reference (elt (rst-hyper-link-reference-match) 0))) + (if (save-excursion + (search-forward reference nil t 1)) + (progn + (search-forward reference nil t 1) + (backward-char 1)) + (when (y-or-n-p "No link reference behind. Search from the beginning?") + (goto-char (point-min)) + (search-forward reference nil t 1) + (backward-char 1))))) + +(defun rst-hyper-link-target-match () + "Match link reference at the target line." + (let (link reference target) + (save-excursion + (when (search-backward ".. _" (line-beginning-position) t 1) + (re-search-forward + "^\\.\\. _`?[[:alnum:][:punct:][:space:]]+`?: " + (line-end-position) t 1) + (setq target (match-string 0)))) + (setq link (substring target 4 -2)) + (if (equal (substring link 0 1) "`") + (setq reference (concat link "_")) + (setq reference (concat " " link "_"))) + (list reference target))) + +(defun rst-link-jump-to-reference () + "Jump from intertext link target to link reference." + (interactive) + (let ((reference (elt (rst-hyper-link-target-match) 0))) + (when (save-excursion + (goto-char (point-max)) + (search-backward reference)) + (goto-char (point-max)) + (search-backward reference)))) + +;--- footnote and citation --- + +(defun rst-footnote-citation-reference-match () + "Match footnote or citation reference around the point." + (let (link reference target) + (save-excursion + (when (search-forward "]_" + (save-excursion + (forward-sentence) + (point)) + t 1) + (re-search-backward "\\[[[:alnum:][:punct:][:space:]]+\\]_" + (save-excursion + (search-backward "[" nil t 1) + (point)) + t) + (setq reference (match-string 0)))) + (setq link (substring reference 1 -2)) + (setq target (concat ".. [" link "]")) + (list reference target))) + +(defun rst-footnote-citation-target-match () + "Match footnote or citation reference at the target line." + (let (link reference target) + (save-excursion + (when (search-backward ".. [" (line-beginning-position) t 1) + (re-search-forward + "^\\.\\. \\[[[:alnum:][:punct:][:space:]]+\\] " + (line-end-position) t 1) + (setq target (match-string 0)))) + (setq link (substring target 4 -2)) + (setq reference (concat " [" link "]_")) + (list reference target))) + +(defun rst-footnote-citation-jump-to-target () + "Jump from footnote or citation reference to target." + (interactive) + (let ((target (elt (rst-footnote-citation-reference-match) 1))) + (when (save-excursion + (goto-char (point-min)) + (search-forward target)) + (goto-char (point-min)) + (search-forward target)))) + +(defun rst-footnote-citation-jump-within-references () + "Jump within references of an footnote or citation, if exist." + (interactive) + (let ((reference (elt (rst-footnote-citation-reference-match) 0))) + (if (save-excursion + (search-forward reference nil t 1)) + (progn + (search-forward reference nil t 1) + (backward-char 1)) + (when (y-or-n-p "No link reference behind. Search from the beginning?") + (goto-char (point-min)) + (search-forward reference nil t 1) + (backward-char 2))))) + +(defun rst-footnote-citation-jump-to-reference () + "Jump from footnote or citation target to reference." + (interactive) + (let ((reference (elt (rst-footnote-citation-target-match) 0))) + (when (save-excursion + (goto-char (point-max)) + (search-backward reference)) + (goto-char (point-max)) + (search-backward reference))))
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.