Initial Commit
[packages] / xemacs-packages / speedbar / sb-texinfo.el
1 ;;; sb-texinfo.el --- provide hierarchical speedbar menu's for texinfo files
2
3 ;; Copyright (c) 2000, 2002 Richard Y. Kim
4
5 ;; Author: Richard Y. Kim, <ryk@ap.com>
6 ;; Maintainer: Richard Y. Kim, <ryk@ap.com>
7 ;; Created: Fri Jun 16 17:23:11 2000
8 ;; Version: $Id: sb-texinfo.el,v 1.9 2005/09/30 20:26:09 zappo Exp $
9 ;; Keywords:
10
11 ;; This program is free software; you can redistribute it and/or
12 ;; modify it under the terms of the GNU General Public License as
13 ;; published by the Free Software Foundation; either version 2 of
14 ;; the License, or (at your option) any later version.
15
16 ;; This program is distributed in the hope that it will be
17 ;; useful, but WITHOUT ANY WARRANTY; without even the implied
18 ;; warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
19 ;; PURPOSE.  See the GNU General Public License for more details.
20
21 ;; You should have received a copy of the GNU General Public
22 ;; License along with this program; if not, write to the Free
23 ;; Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
24 ;; MA 02110-1301 USA
25
26 ;;; Commentary:
27 ;;
28 ;; The speedbar mode provides support for texinfo files by creating
29 ;; tags using imenu.  This presentation do not reflect the natural
30 ;; hierarchy of the texinfo document.
31 ;;
32 ;; This small add-on to speedbar provides an alternate way to view the
33 ;; document which shows the natural hierarchy of the document.  This
34 ;; shows the same information that `M-x texinfo-show-structure'
35 ;; displays, but in the speedbar frame with the speedbar user
36 ;; interface.
37
38 ;; Installtation procedure:
39 ;;   Install speedbar 0.12 or later.
40 ;;   Add the following to your ~/.emacs file:
41 ;;   (eval-after-load "speedbar" '(load-library "sb-texinfo"))
42
43 ;; Known Problems:
44 ;;   Does not look inside files included via @include directive.
45 ;;
46 ;;   The indentations of nodes with and without subnodes could be better.
47 ;;
48 ;;   Clicking on nodes with subnodes only shows subnodes rather than
49 ;;   displaying the node content on the target frame.  Instead the first
50 ;;   subnode on the speedbar has to be clicked.  I believe this can be
51 ;;   fixed if a custom speedbar button display routine is written rather
52 ;;   than using the built-in function speedbar-insert-generic-list.
53 ;;   If I learn to do this, I will, but I make no promises.
54 ;;
55 ;;   Potential problem with auctex 9.9p users.  Auctex provides it's
56 ;;   own texinfo mode which does not use texinfo-mode-hook.  Make sure
57 ;;   you do not use texinfo mode provided by auctex!
58
59 ;;; Change Log:
60 ;;;
61 ;;; 1.7 - By Eric Ludlam <zappo@gnu.org>
62 ;;;       In `speedbar-fetch-dynamic-texinfo', set the buffer to file
63 ;;;       to correspond to a speedbar change.
64 ;;;
65 ;;; 1.6 - By Eric Ludlam <zappo@gnu.org>
66 ;;;       speedbar-insert-texinfo-list no longer sets sthm to nil.
67 ;;;       speedbar-format-texinfo-list uses new positioned group for
68 ;;;       any chapter w/ sections (etc)  Also set new
69 ;;;       speedbar-generic-list-{group-expand|tag}-button-list to
70 ;;;       nice values.
71 ;;;
72 ;;; 1.5 - speedbar-tag-hierarchy-method is set to nil by
73 ;;;       speedbar-insert-texinfo-list as well as
74 ;;;       speedbar-fetch-dynamic-texinfo.  This is needed in order to
75 ;;;       have the texinfo nodes displayed in correct order.
76 ;;;
77 ;;; 1.4 - speedbar-tag-hierarchy-method is now set to nil by
78 ;;;       speedbar-fetch-dynamic-texinfo after making it buffer local
79 ;;;       first.  I thought this was buffer-local variable alread, but
80 ;;;       it is not.  Also added installation instruction.
81 ;;;
82 ;;; 1.3 - Added bunch of comments in the code as well as installation
83 ;;;       instruction.  speedbar-texinfo-mode-hook now turns on the
84 ;;;       speedbar mode.
85 ;;;
86 ;;; 1.2 - Use newly created variable speedbar-texinfo-section-regexp rather
87 ;;;       than texinfo-section-types-regexp, because the latter does not
88 ;;;       have "top" in it.
89 ;;;
90 ;;;       Also added a hook to texinfo-mode-hook which sets
91 ;;;       speedbar-tag-hierarchy-method to nil at Eric Ludlam's
92 ;;;       suggestion.
93 ;;;
94 ;;; 1.1 - first draft sent to Eric. on June 16, 2000.
95
96 ;;; Code:
97
98 (require 'speedbar)
99
100 ;; GNU Emacs 20.7 comes with speedbar 0.8.1 bundled which does not work
101 ;; with sb-texinfo.  Lacking speedbar-version variable, check whether
102 ;; speedbar-dynamic-tags-function-list is bound which was introduced after
103 ;; 0.8.1.
104 (or (boundp 'speedbar-dynamic-tags-function-list)
105     (error "Speedbar 0.11 or newer is required to use sb-texinfo."))
106
107 ;; Attach these new functions to handle texinfo-mode.
108 (add-to-list 'speedbar-dynamic-tags-function-list
109              '(speedbar-fetch-dynamic-texinfo . speedbar-insert-texinfo-list))
110
111 ;; speedbar-texinfo-section-regexp is same as texinfo-section-types-regexp
112 ;; except that it has "top" entry.
113 (defconst speedbar-texinfo-section-regexp
114   "^@\\(top \\|chapter \\|sect\\|subs\\|subh\\|unnum\\|major\\|chapheading \\|heading \\|appendix\\)")
115
116 (defun speedbar-fetch-dynamic-texinfo ( filename )
117   "This returns t if the major mode of the current buffer is not 'texinfo-mode.
118 If it is 'texinfo-mode, then this returns a list where each element is
119 (LEVEL NAME . MARKER).
120 LEVEL is 0, 1, 2, or 3 corresponding to chapter section,
121 subsection, and subsubsection respectively.
122 NAME is the name of the node.
123 MARKER is emacs marker that points to the beginning of the node.
124 The elements in the the list returned are in ascending order of the MARKER.
125 This function along with it's parter, speedbar-insert-texinfo-list, are
126 designed to be added to the speedbar-dynamic-tags-function-list list."
127   (set-buffer (find-file-noselect filename))
128   (if (not (eq major-mode 'texinfo-mode))
129       t
130     (condition-case nil
131         (save-excursion
132
133           ;; Set speedbar-tag-hierarchy-method to nil so that
134           ;; speedbar-create-tag-hierarchy won't reorder the list.
135           ;; Make it buffer local so that the global value is not touched.
136           (make-local-variable 'speedbar-tag-hierarchy-method)
137           (setq speedbar-tag-hierarchy-method nil)
138
139           (set (make-local-variable
140                 'speedbar-generic-list-group-expand-button-type)
141                'expandtag)
142           (set (make-local-variable
143                 'speedbar-generic-list-tag-button-type)
144                'statictag)
145
146           (let ((heading-to-level
147                  '(("top" . 0)
148                    ("chapter" . 0) ("section" . 1)
149                    ("subsection" . 2) ("subsubsection" . 3)
150                    ("unnumbered" . 0) ("unnumberedsec" . 1)
151                    ("unnumberedsubsec" . 2) ("unnumberedsubsubsec" . 3)
152                    ("chapheading" . 0) ("heading" . 1)
153                    ("subheading" . 2) ("subsubheading" . 3)
154                    ("appendix" . 0) ("appendixsec" . 1)
155                    ("appendixsubsec" . 2) ("appendixsubsubsec" . 3)
156                    ("centerchap" . 0) ("majorheading" . 0)))
157                 pos-beg title level section alist)
158             ;; Create a list of all nodes
159             (goto-char (point-min))
160             (while (re-search-forward speedbar-texinfo-section-regexp nil t)
161               (goto-char (1+ (match-beginning 0))) ;right after @
162               (setq pos-beg (point-marker))
163               (setq section (symbol-name (read (current-buffer))))
164               (setq level (cdr (assoc section heading-to-level)))
165               (setq title (buffer-substring
166                            (progn (skip-chars-forward " \t")
167                                   (point))
168                            (progn (skip-chars-forward "^,\n")
169                                   (skip-chars-backward " \t")
170                                   (point))))
171               (setq alist (cons (cons level (cons title pos-beg)) alist)))
172             (nreverse alist)))
173       (error t))))
174
175 (defun speedbar-format-texinfo-list ( lst level)
176   "See `speedbar-fetch-dynamic-texinfo' for description of LST.
177 LEVEL should be 0 unless this is called recursively.
178 This function converts LST from a flat list structure into
179 a hierarchical list suitable to be passed on to `speedbar-insert-texinfo-list'.
180 This function creates the hierarchical list recursively.
181 On first pass all the nodes of each chapter are grouped into a list.
182 Then each of these lists are recursively converted so that all nodes
183 of each section are grouped together."
184   (let (new-list elem section-list)
185     (while lst
186       (setq section-list (list (cdr (car lst))))
187       (setq lst  (cdr lst))
188       (while (and lst (> (car (car lst)) level))
189         (setq section-list (cons (car lst) section-list))
190         (setq lst  (cdr lst)))
191       (setq new-list (cons (nreverse section-list) new-list)))
192     (setq new-list (nreverse new-list))
193     ;; Each member of new-list is a list of all chapters (on first pass), i.e.,
194     ;; ( ((chap1 marker) (1 sec1 marker) ...)  ((chap2 marker) ...) ... )
195
196     ;; Start recursion.
197     (setq level (1+ level))
198     (mapcar '(lambda (x)
199                (if (eq (length x) 1)
200                    ;;(cons (car (car x)) x)
201                    (car x)
202                  (let ((head (car x)))
203                    (cons (car head)
204                          (cons (cdr head)
205                                (speedbar-format-texinfo-list
206                                 (cdr x) level))))))
207             new-list)))
208
209 (defun speedbar-insert-texinfo-list (indent lst)
210   "Insert a list of generic tokens reorganized into chapeters.
211 INDENT is the current level of indentation, and LST is the list of tokens."
212   (speedbar-insert-generic-list indent
213                                 (speedbar-format-texinfo-list lst 0)
214                                 'speedbar-tag-expand
215                                 'speedbar-tag-find))
216
217 (provide 'sb-texinfo)
218 ;;; sb-texinfo.el ends here
219