aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--etc/NEWS2
-rw-r--r--lisp/ChangeLog12
-rw-r--r--lisp/textmodes/rst.el282
3 files changed, 189 insertions, 107 deletions
diff --git a/etc/NEWS b/etc/NEWS
index b63430b0803..3b4b06341c5 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -419,6 +419,8 @@ the experience for Sphinx users.
419 419
420*** Package version in `rst-version'. 420*** Package version in `rst-version'.
421 421
422*** Support `imenu' and `which-func'.
423
422** New `derived-mode' filter for Ibuffer, bound to `/ M'. 424** New `derived-mode' filter for Ibuffer, bound to `/ M'.
423`/ m' is now bound to filter by used-mode, which used to be bound to `/ M'. 425`/ m' is now bound to filter by used-mode, which used to be bound to `/ M'.
424 426
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index 8b99fc29252..fd7bc3defec 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,15 @@
12012-09-20 Stefan Merten <smerten@oekonux.de>
2
3 * rst.el: Integrate support for `imenu' and `which-function'.
4 Fixes feature request bug#11711.
5 (rst-mode): Create `imenu-create-index-function'.
6 (rst-get-stripped-line): Delete after refactoring.
7 (rst-section-tree, rst-section-tree-rec)
8 (rst-section-tree-point): Refactor and document properly.
9 (rst-imenu-find-adornments-for-position)
10 (rst-imenu-convert-cell, rst-imenu-create-index): New
11 function.
12
12012-09-20 Stefan Monnier <monnier@iro.umontreal.ca> 132012-09-20 Stefan Monnier <monnier@iro.umontreal.ca>
2 14
3 * emacs-lisp/macroexp.el (macroexp--obsolete-warning): New function. 15 * emacs-lisp/macroexp.el (macroexp--obsolete-warning): New function.
diff --git a/lisp/textmodes/rst.el b/lisp/textmodes/rst.el
index 47a821c0148..56b0ee47e4a 100644
--- a/lisp/textmodes/rst.el
+++ b/lisp/textmodes/rst.el
@@ -112,6 +112,9 @@
112 112
113;; FIXME: Use `testcover'. 113;; FIXME: Use `testcover'.
114 114
115;; FIXME: The adornment classification often called `ado' should be a
116;; `defstruct'.
117
115;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 118;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
116;; Support for `testcover' 119;; Support for `testcover'
117 120
@@ -214,7 +217,7 @@ and before TAIL-RE and DELIM-RE in VAR or DEFAULT for no match."
214;; Use CVSHeader to really get information from CVS and not other version 217;; Use CVSHeader to really get information from CVS and not other version
215;; control systems. 218;; control systems.
216(defconst rst-cvs-header 219(defconst rst-cvs-header
217 "$CVSHeader: sm/rst_el/rst.el,v 1.309.2.1 2012-09-17 17:30:49 stefan Exp $") 220 "$CVSHeader: sm/rst_el/rst.el,v 1.324 2012-09-20 18:52:46 stefan Exp $")
218(defconst rst-cvs-rev 221(defconst rst-cvs-rev
219 (rst-extract-version "\\$" "CVSHeader: \\S + " "[0-9]+\\(?:\\.[0-9]+\\)+" 222 (rst-extract-version "\\$" "CVSHeader: \\S + " "[0-9]+\\(?:\\.[0-9]+\\)+"
220 " .*" rst-cvs-header "0.0") 223 " .*" rst-cvs-header "0.0")
@@ -844,6 +847,12 @@ highlighting.
844 (set (make-local-variable 'uncomment-region-function) 847 (set (make-local-variable 'uncomment-region-function)
845 'rst-uncomment-region) 848 'rst-uncomment-region)
846 849
850 ;; Imenu and which function.
851 ;; FIXME: Check documentation of `which-function' for alternative ways to
852 ;; determine the current function name.
853 (set (make-local-variable 'imenu-create-index-function)
854 'rst-imenu-create-index)
855
847 ;; Font lock. 856 ;; Font lock.
848 (set (make-local-variable 'font-lock-defaults) 857 (set (make-local-variable 'font-lock-defaults)
849 '(rst-font-lock-keywords 858 '(rst-font-lock-keywords
@@ -2170,126 +2179,112 @@ adjust. If bullets are found on levels beyond the
2170;; Table of contents 2179;; Table of contents
2171;; ================= 2180;; =================
2172 2181
2173(defun rst-get-stripped-line () 2182;; FIXME: Return value should be a `defstruct'.
2174 "Return the line at cursor, stripped from whitespace."
2175 (re-search-forward (rst-re "\\S .*\\S ") (line-end-position))
2176 (buffer-substring-no-properties (match-beginning 0)
2177 (match-end 0)) )
2178
2179(defun rst-section-tree () 2183(defun rst-section-tree ()
2180 "Get the hierarchical tree of section titles. 2184 "Return the hierarchical tree of section titles.
2181 2185A tree entry looks like ((TITLE MARKER) CHILD...). TITLE is the
2182Returns a hierarchical tree of the sections titles in the 2186stripped text of the section title. MARKER is a marker for the
2183document. This can be used to generate a table of contents for 2187beginning of the title text. For the top node or a missing
2184the document. The top node will always be a nil node, with the 2188section level node TITLE is nil and MARKER points to the title
2185top level titles as children (there may potentially be more than 2189text of the first child. Each CHILD is another tree entry. The
2186one). 2190CHILD list may be empty."
2187
2188Each section title consists in a cons of the stripped title
2189string and a marker to the section in the original text document.
2190
2191If there are missing section levels, the section titles are
2192inserted automatically, and the title string is set to nil, and
2193the marker set to the first non-nil child of itself.
2194Conceptually, the nil nodes--i.e.\ those which have no title--are
2195to be considered as being the same line as their first non-nil
2196child. This has advantages later in processing the graph."
2197
2198 (let ((hier (rst-get-hierarchy)) 2191 (let ((hier (rst-get-hierarchy))
2199 (levels (make-hash-table :test 'equal :size 10)) 2192 (ch-sty2level (make-hash-table :test 'equal :size 10))
2200 lines) 2193 lev-ttl-mrk-l)
2201 2194
2202 (let ((lev 0)) 2195 (let ((lev 0))
2203 (dolist (ado hier) 2196 (dolist (ado hier)
2204 ;; Compare just the character and indent in the hash table. 2197 ;; Compare just the character and indent in the hash table.
2205 (puthash (cons (car ado) (cadr ado)) lev levels) 2198 (puthash (cons (car ado) (cadr ado)) lev ch-sty2level)
2206 (incf lev))) 2199 (incf lev)))
2207 2200
2208 ;; Create a list of lines that contains (text, level, marker) for each 2201 ;; Create a list that contains (LEVEL TITLE MARKER) for each adornment.
2209 ;; adornment.
2210 (save-excursion 2202 (save-excursion
2211 (setq lines 2203 (setq lev-ttl-mrk-l
2212 (mapcar (lambda (ado) 2204 (mapcar (lambda (ado)
2213 (goto-char (point-min)) 2205 (goto-char (point-min))
2214 (forward-line (1- (car ado))) 2206 (1value ;; This should really succeed.
2215 (list (gethash (cons (cadr ado) (caddr ado)) levels) 2207 (forward-line (1- (car ado))))
2216 (rst-get-stripped-line) 2208 (list (gethash (cons (cadr ado) (caddr ado)) ch-sty2level)
2217 (progn 2209 ;; Get title.
2218 (beginning-of-line 1) 2210 (save-excursion
2219 (point-marker)))) 2211 (if (re-search-forward
2212 (rst-re "\\S .*\\S ") (line-end-position) t)
2213 (buffer-substring-no-properties
2214 (match-beginning 0) (match-end 0))
2215 ""))
2216 (point-marker)))
2220 (rst-find-all-adornments)))) 2217 (rst-find-all-adornments))))
2221 (let ((lcontnr (cons nil lines))) 2218 (cdr (rst-section-tree-rec lev-ttl-mrk-l -1))))
2222 (rst-section-tree-rec lcontnr -1)))) 2219
2223 2220;; FIXME: Return value should be a `defstruct'.
2224 2221(defun rst-section-tree-rec (remaining lev)
2225(defun rst-section-tree-rec (ados lev) 2222 "Process the first entry of REMAINING expected to be on level LEV.
2226 "Recursive guts of the section tree construction. 2223REMAINING is the remaining list of adornments consisting
2227ADOS is a cons cell whose cdr is the remaining list of 2224of (LEVEL TITLE MARKER) entries.
2228adornments, and we change it as we consume them. LEV is 2225
2229the current level of that node. This function returns a 2226Return (UNPROCESSED (TITLE MARKER) CHILD...) for the first entry
2230pair of the subtree that was built. This treats the ADOS 2227of REMAINING where TITLE is nil if the expected level is not
2231list destructively." 2228matched. UNPROCESSED is the list of still unprocessed entries.
2232 2229Each CHILD is a child of this entry in the same format but
2233 (let ((nado (cadr ados)) 2230without UNPROCESSED."
2234 node 2231 (let ((cur (car remaining))
2235 children) 2232 (unprocessed remaining)
2236 2233 ttl-mrk children)
2237 ;; If the next adornment matches our level. 2234 ;; If the current adornment matches expected level.
2238 (when (and nado (= (car nado) lev)) 2235 (when (and cur (= (car cur) lev))
2239 ;; Pop the next adornment and create the current node with it. 2236 ;; Consume the current entry and create the current node with it.
2240 (setcdr ados (cddr ados)) 2237 (setq unprocessed (cdr remaining))
2241 (setq node (cdr nado)) ) 2238 (setq ttl-mrk (cdr cur)))
2242 ;; Else we let the node title/marker be unset. 2239
2243 2240 ;; Build the child nodes as long as they have deeper level.
2244 ;; Build the child nodes. 2241 (while (and unprocessed (> (caar unprocessed) lev))
2245 (while (and (cdr ados) (> (caadr ados) lev)) 2242 (let ((rem-children (rst-section-tree-rec unprocessed (1+ lev))))
2246 (setq children 2243 (setq children (cons (cdr rem-children) children))
2247 (cons (rst-section-tree-rec ados (1+ lev)) 2244 (setq unprocessed (car rem-children))))
2248 children)))
2249 (setq children (reverse children)) 2245 (setq children (reverse children))
2250 2246
2251 ;; If node is still unset, we use the marker of the first child. 2247 (cons unprocessed
2252 (when (eq node nil) 2248 (cons (or ttl-mrk
2253 (setq node (cons nil (cdaar children)))) 2249 ;; Node on this level missing - use nil as text and the
2254 2250 ;; marker of the first child.
2255 ;; Return this node with its children. 2251 (cons nil (cdaar children)))
2256 (cons node children))) 2252 children))))
2257 2253
2258 2254(defun rst-section-tree-point (tree &optional point)
2259(defun rst-section-tree-point (node &optional point) 2255 "Return section containing POINT by returning the closest node in TREE.
2260 "Find tree node at point. 2256TREE is a section tree as returned by `rst-section-tree'
2261Given a computed and valid section tree in NODE and a point 2257consisting of (NODE CHILD...) entries. POINT defaults to the
2262POINT (default being the current point in the current buffer), 2258current point. A NODE must have the structure (IGNORED MARKER
2263find and return the node within the section tree where the cursor 2259...).
2264lives. 2260
2265 2261Return (PATH NODE CHILD...). NODE is the node where POINT is in
2266Return values: a pair of (parent path, container subtree). 2262if any. PATH is a list of nodes from the top of the tree down to
2267The parent path is simply a list of the nodes above the 2263and including NODE. List of CHILD are the children of NODE if
2268container subtree node that we're returning." 2264any."
2269 2265 (setq point (or point (point)))
2270 (let (path outtree) 2266 (let ((cur (car tree))
2271 2267 (children (cdr tree)))
2272 (let* ((curpoint (or point (point)))) 2268 ;; Point behind current node?
2273 2269 (if (and (cadr cur) (>= point (cadr cur)))
2274 ;; Check if we are before the current node. 2270 ;; Iterate all the children, looking for one that might contain the
2275 (if (and (cadar node) (>= curpoint (cadar node))) 2271 ;; current section.
2276 2272 (let (found)
2277 ;; Iterate all the children, looking for one that might contain the 2273 (while (and children (>= point (cadaar children)))
2278 ;; current section. 2274 (setq found children
2279 (let ((curnode (cdr node)) 2275 children (cdr children)))
2280 last) 2276 (if found
2281 2277 ;; Found section containing point in children.
2282 (while (and curnode (>= curpoint (cadaar curnode))) 2278 (let ((sub (rst-section-tree-point (car found) point)))
2283 (setq last curnode 2279 ;; Extend path with current node and return NODE CHILD... from
2284 curnode (cdr curnode))) 2280 ;; sub.
2285 2281 (cons (cons cur (car sub)) (cdr sub)))
2286 (if last 2282 ;; Point in this section: Start a new path with current node and
2287 (let ((sub (rst-section-tree-point (car last) curpoint))) 2283 ;; return current NODE CHILD...
2288 (setq path (car sub) 2284 (cons (list cur) tree)))
2289 outtree (cdr sub))) 2285 ;; Current node behind point: start a new path with current node and
2290 (setq outtree node))))) 2286 ;; no NODE CHILD...
2291 (cons (cons (car node) path) outtree))) 2287 (list (list cur)))))
2292
2293 2288
2294(defgroup rst-toc nil 2289(defgroup rst-toc nil
2295 "Settings for reStructuredText table of contents." 2290 "Settings for reStructuredText table of contents."
@@ -4132,6 +4127,79 @@ buffer, if the region is not selected."
4132 )) 4127 ))
4133 4128
4134 4129
4130;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4131;; Imenu support.
4132
4133;; FIXME: Integrate this properly. Consider a key binding.
4134
4135;; Based on code from Masatake YAMATO <yamato@redhat.com>.
4136
4137(defun rst-imenu-find-adornments-for-position (adornments pos)
4138 "Find adornments cell in ADORNMENTS for position POS."
4139 (let ((a nil))
4140 (while adornments
4141 (if (and (car adornments)
4142 (eq (car (car adornments)) pos))
4143 (setq a adornments
4144 adornments nil)
4145 (setq adornments (cdr adornments))))
4146 a))
4147
4148(defun rst-imenu-convert-cell (elt adornments)
4149 "Convert a cell ELT in a tree returned from `rst-section-tree' to imenu index.
4150ADORNMENTS is used as hint information for conversion."
4151 (let* ((kar (car elt))
4152 (kdr (cdr elt))
4153 (title (car kar)))
4154 (if kar
4155 (let* ((p (marker-position (cadr kar)))
4156 (adornments
4157 (rst-imenu-find-adornments-for-position adornments p))
4158 (a (car adornments))
4159 (adornments (cdr adornments))
4160 ;; FIXME: Overline adornment characters need to be in front so
4161 ;; they become visible even for long title lines. May be
4162 ;; an additional level number is also useful.
4163 (title (format "%s%s%s"
4164 (make-string (1+ (nth 3 a)) (nth 1 a))
4165 title
4166 (if (eq (nth 2 a) 'simple)
4167 ""
4168 (char-to-string (nth 1 a))))))
4169 (cons title
4170 (if (null kdr)
4171 p
4172 (cons
4173 ;; A bit ugly but this make which-func happy.
4174 (cons title p)
4175 (mapcar (lambda (elt0)
4176 (rst-imenu-convert-cell elt0 adornments))
4177 kdr)))))
4178 nil)))
4179
4180;; FIXME: Document title and subtitle need to be handled properly. They should
4181;; get an own "Document" top level entry.
4182(defun rst-imenu-create-index ()
4183 "Create index for imenu.
4184Return as described for `imenu--index-alist'."
4185 (rst-reset-section-caches)
4186 (let ((tree (rst-section-tree))
4187 ;; Translate line notation to point notation.
4188 (adornments (save-excursion
4189 (mapcar (lambda (ln-ado)
4190 (cons (progn
4191 (goto-char (point-min))
4192 (forward-line (1- (car ln-ado)))
4193 ;; FIXME: Need to consider
4194 ;; `imenu-use-markers' here?
4195 (point))
4196 (cdr ln-ado)))
4197 (rst-find-all-adornments)))))
4198 (delete nil (mapcar (lambda (elt)
4199 (rst-imenu-convert-cell elt adornments))
4200 tree))))
4201
4202
4135;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 4203;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4136;; Generic text functions that are more convenient than the defaults. 4204;; Generic text functions that are more convenient than the defaults.
4137 4205