1 ;;; sb-info --- Speedbar support for Info
3 ;; Copyright (C) 1997, 1998, 2000, 2001, 2002, 2005 Free Software Foundation
5 ;; Author: Eric M. Ludlam <zappo@gnu.ai.mit.edu>
7 ;; Keywords: file, tags, tools
8 ;; X-RCS: $Id: sb-info.el.upstream,v 1.1 2007-12-02 07:28:59 michaels Exp $
10 ;; This file is patch of GNU Emacs.
12 ;; This program is free software; you can redistribute it and/or modify
13 ;; it under the terms of the GNU General Public License as published by
14 ;; the Free Software Foundation; either version 2, or (at your option)
17 ;; This program is distributed in the hope that it will be useful,
18 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 ;; GNU General Public License for more details.
22 ;; You should have received a copy of the GNU General Public License
23 ;; along with this program; if not, you can either send email to this
24 ;; program's author (see below) or write to:
26 ;; The Free Software Foundation, Inc.
28 ;; Cambridge, MA 02139, USA.
30 ;; Please send bug reports, etc. to zappo@gnu.org
35 ;; Speedbar provides a frame in which files, and locations in
36 ;; files are displayed. These functions provide Info specific support,
37 ;; showing links and addresses in the side-bar.
39 ;; To enable in Emacs 20.2 or earlier, add this to your .emacs file.
40 ;; (autoload 'Info-speedbar-buttons "sb-info"
41 ;; "Info specific speedbar button generator.")
43 ;; This file requires speedbar and Info.
46 ;; 0.1 - first revision copied from speedbspec.el V 0.1.1
47 ;; 0.1.1 - No longer require speedbspec
48 ;; 0.2 - Added a speedbar major mode for displaying Info nodes, and modeled
49 ;; the minor mode after it. Completely replaced the old info display
50 ;; with the major mode, and mixed them to move nicely from major to
51 ;; minor mode effortlessly.
52 ;; 0.2.1 Added section adding major display mode at load time.
58 (defvar Info-speedbar-key-map nil
59 "Keymap used when in the info display mode.")
61 (defun Info-install-speedbar-variables ()
62 "Install those variables used by speedbar to enhance Info."
63 (if Info-speedbar-key-map
65 (setq Info-speedbar-key-map (speedbar-make-specialized-keymap))
67 ;; Basic tree features
68 (define-key Info-speedbar-key-map "e" 'speedbar-edit-line)
69 (define-key Info-speedbar-key-map "\C-m" 'speedbar-edit-line)
70 (define-key Info-speedbar-key-map "+" 'speedbar-expand-line)
71 (define-key Info-speedbar-key-map "=" 'speedbar-expand-line)
72 (define-key Info-speedbar-key-map "-" 'speedbar-contract-line)
73 (define-key Info-speedbar-key-map " " 'speedbar-toggle-line-expansion)
76 (speedbar-add-expansion-list '("Info" Info-speedbar-menu-items
78 Info-speedbar-hierarchy-buttons)))
80 (defvar Info-speedbar-menu-items
81 '(["Browse Node" speedbar-edit-line t]
82 ["Expand Node" speedbar-expand-line
83 (save-excursion (beginning-of-line)
84 (looking-at "[0-9]+: *.\\+. "))]
85 ["Contract Node" speedbar-contract-line
86 (save-excursion (beginning-of-line)
87 (looking-at "[0-9]+: *.-. "))]
89 "Additional menu-items to add to speedbar frame.")
91 ;; Make sure our special speedbar major mode is loaded
92 (if (featurep 'speedbar)
93 (Info-install-speedbar-variables)
94 (add-hook 'speedbar-load-hook 'Info-install-speedbar-variables))
96 ;;; Info hierarchy display method
98 (defun Info-speedbar-browser ()
99 "Initialize speedbar to display an info node browser.
100 This will add a speedbar major display mode."
103 ;; Make sure that speedbar is active
104 (speedbar-frame-mode 1)
105 ;; Now, throw us into Info mode on speedbar.
106 (speedbar-change-initial-expansion-list "Info")
109 (defvar Info-speedbar-image-button-alist
110 '(("<+>" . ezimage-document-plus)
111 ("<->" . ezimage-document-minus)
112 ("[+]" . ezimage-page-plus)
113 ("[-]" . ezimage-page-minus)
114 ("[?]" . ezimage-page)
115 ("[ ]" . ezimage-page)
117 "Image buttons used for Info mode.")
119 (defun Info-speedbar-hierarchy-buttons (directory depth &optional node)
120 "Display an Info directory hierarchy in speedbar.
121 DIRECTORY is the current directory in the attached frame.
122 DEPTH is the current indentation depth.
123 NODE is an optional argument that is used to represent the
124 specific node to expand."
126 (save-excursion (goto-char (point-min))
127 (looking-at "Info Nodes:")))
128 ;; Update our "current node" maybe?
130 ;; We cannot use the generic list code, that depends on all leaves
131 ;; being known at creation time.
133 (speedbar-with-writable (insert "Info Nodes:\n")))
134 (let ((completions nil)
135 (speedbar-expand-image-button-alist
136 Info-speedbar-image-button-alist))
137 (dframe-select-attached-frame speedbar-frame)
138 (save-window-excursion
140 (Info-speedbar-fetch-file-nodes (or node '"(dir)top"))))
141 (select-frame speedbar-frame)
143 (speedbar-with-writable
145 (speedbar-make-tag-line (if (= depth 0)
148 ?+ 'Info-speedbar-expand-node
149 (cdr (car completions))
150 (car (car completions))
151 'Info-speedbar-goto-node
152 (cdr (car completions))
154 (setq completions (cdr completions)))
158 (defun Info-speedbar-goto-node (text node indent)
159 "When user clicks on TEXT, goto an info NODE.
160 The INDENT level is ignored."
161 (dframe-select-attached-frame speedbar-frame)
162 (let* ((buff (or (get-buffer "*info*")
163 (progn (info) (get-buffer "*info*"))))
164 (bwin (get-buffer-window buff 0)))
168 (raise-frame (window-frame bwin)))
169 (if dframe-power-click
170 (let ((pop-up-frames t)) (select-window (display-buffer buff)))
171 (dframe-select-attached-frame speedbar-frame)
172 (switch-to-buffer buff)))
173 (if (string-match "^(\\([^)]+\\))\\([^,:]+\\)$" node)
174 (let ((file (match-string 1 node))
175 (node (match-string 2 node)))
176 (Info-find-node file node)
177 ;; If we do a find-node, and we were in info mode, restore
178 ;; the old default method. Once we are in info mode, it makes
179 ;; sense to return to whatever method the user was using before.
180 (if (string= speedbar-initial-expansion-list-name "Info")
181 (speedbar-change-initial-expansion-list
182 speedbar-previously-used-expansion-list-name))))))
184 (defun Info-speedbar-expand-node (text token indent)
185 "Expand the node the user clicked on.
186 TEXT is the text of the button we clicked on, a + or - item.
187 TOKEN is data related to this node (NAME . FILE).
188 INDENT is the current indentation depth."
189 (let ((speedbar-expand-image-button-alist Info-speedbar-image-button-alist))
190 (cond ((string-match "+" text) ;we have to expand this file
191 (speedbar-change-expand-button-char ?-)
192 (if (speedbar-with-writable
194 (end-of-line) (forward-char 1)
195 (Info-speedbar-hierarchy-buttons nil (1+ indent) token)))
196 (speedbar-change-expand-button-char ?-)
197 (speedbar-change-expand-button-char ??)))
198 ((string-match "-" text) ;we have to contract this node
199 (speedbar-change-expand-button-char ?+)
200 (speedbar-delete-subblock indent))
201 (t (error "Ooops... not sure what to do")))
202 (speedbar-center-buffer-smartly)))
204 (defun Info-speedbar-fetch-file-nodes (nodespec)
205 "Fetch the subnodes from the info NODESPEC.
206 NODESPEC is a string of the form: (file)node.
207 Optional THISFILE represends the filename of"
209 ;; Set up a buffer we can use to fake-out Info.
210 (set-buffer (get-buffer-create "*info-browse-tmp*"))
211 (if (not (equal major-mode 'Info-mode))
213 ;; Get the node into this buffer
214 (if (string-match "^(\\([^)]+\\))\\([^,:]+\\)$" nodespec)
215 (let ((file (match-string 1 nodespec))
216 (node (match-string 2 nodespec)))
217 (Info-find-node file node))
218 (error "Node %s not found!" nodespec))
219 ;; Scan the created buffer
220 (goto-char (point-min))
221 (let ((completions nil)
222 (thisfile (progn (string-match "^(\\([^)]+\\))" nodespec)
223 (match-string 1 nodespec))))
224 ;; Always skip the first one...
225 (re-search-forward "\n\\* \\([^:\t\n]*\\):" nil t)
226 (while (re-search-forward "\n\\* \\([^:\t\n]*\\):" nil t)
227 (let ((name (match-string 1)))
228 (if (looking-at " *\\(([^)]+)[^.\n]+\\)\\.")
229 (setq name (cons name (match-string 1)))
230 (if (looking-at "[ \t]*\\(([^)]+)\\)\\.")
231 (setq name (cons name (concat (match-string 1) "Top")))
232 (if (looking-at " \\([^.]+\\).")
234 (cons name (concat "(" thisfile ")" (match-string 1))))
235 (setq name (cons name (concat "(" thisfile ")" name))))))
236 (setq completions (cons name completions))))
237 (nreverse completions))))
239 ;;; Info mode node listing
241 (defun Info-speedbar-buttons (buffer)
242 "Create a speedbar display to help navigation in an Info file.
243 BUFFER is the buffer speedbar is requesting buttons for."
244 (if (save-excursion (goto-char (point-min))
245 (not (looking-at "Info Nodes:")))
247 (Info-speedbar-hierarchy-buttons nil 0)
252 ;;; Overriding preinstalled code.
254 (eval-after-load "info" '(require 'sb-info))
255 ;;; sb-info.el ends here