-;;; speedbar --- quick access to files and tags in a frame
+;;; speedbar.el --- quick access to files and tags in a frame
-;;; Copyright (C) 1996, 97, 98, 99, 00 Free Software Foundation
+;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
+;; 2004, 2005 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
-;; Version: 0.11
+;; Version: 0.11a
;; Keywords: file, tags, tools
;; This file is part of GNU Emacs.
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
;;; Commentary:
;;
;; applicable, tags in the active file can be expanded.
;;
;; To add new supported files types into speedbar, use the function
-;; `speedbar-add-supported-extension' If speedbar complains that the
+;; `speedbar-add-supported-extension'. If speedbar complains that the
;; file type is not supported, that means there is no built in
;; support from imenu, and the etags part wasn't set up correctly. You
;; may add elements to `speedbar-supported-extension-expressions' as long
;; as it is done before speedbar is loaded.
;;
;; To prevent speedbar from following you into certain directories
-;; use the function `speedbar-add-ignored-path-regexp' too add a new
+;; use the function `speedbar-add-ignored-path-regexp' to add a new
;; regular expression matching a type of path. You may add list
;; elements to `speedbar-ignored-path-expressions' as long as it is
;; done before speedbar is loaded.
;; which controls how tags are layed out. It is actually a list of
;; functions that filter the data. The default groups large tag lists
;; into sub-lists. A long flat list can be used instead if needed.
-;; Other filters could be easily added.
+;; Other filters can be easily added.
;;
-;; AUC-TEX users: The imenu tags for AUC-TEX mode don't work very
+;; AUCTEX users: The imenu tags for AUCTEX mode doesn't work very
;; well. Use the imenu keywords from tex-mode.el for better results.
;;
;; This file requires the library package assoc (association lists)
;; Adding a speedbar specialized display mode:
;;
;; Speedbar can be configured to create a special display for certain
-;; modes that do not display tradition file/tag data. Rmail, Info,
+;; modes that do not display traditional file/tag data. Rmail, Info,
;; and the debugger are examples. These modes can, however, benefit
;; from a speedbar style display in their own way.
;;
;; `speedbar-insert-generic-list'. If you use
;; `speedbar-insert-generic-list', also read the doc for
;; `speedbar-tag-hierarchy-method' in case you wish to override it.
-;; The function `speedbar-with-attached-buffer' brings you back to the
+;; The macro `speedbar-with-attached-buffer' brings you back to the
;; buffer speedbar is displaying for.
;;
;; For those functions that make buttons, the "function" should be a
;; functions are `speedbar-change-expand-button-char',
;; `speedbar-delete-subblock', and `speedbar-center-buffer-smartly'.
;; The variable `speedbar-power-click' is set to t in your functions
-;; when the user shift-clicks. This indications anything from
+;; when the user shift-clicks. This is an indication of anything from
;; refreshing cached data to making a buffer appear in a new frame.
;;
;; If you wish to add to the default speedbar menu for the case of
;; splice in. KEYMAP is a symbol holding the keymap to use, and
;; BUTTON-FUNCTIONS are the function names to call, in order, to create
;; the display.
-;; Another tweekable variable is `speedbar-stealthy-function-list'
+;; Another tweakable variable is `speedbar-stealthy-function-list'
;; which is of the form (NAME &rest FUNCTION ...). NAME is the string
;; name matching `speedbar-add-expansion-list'. (It does not need to
;; exist.). This provides additional display info which might be
;; time-consuming to calculate.
;; Lastly, `speedbar-mode-functions-list' allows you to set special
-;; function overrides. At the moment very few functions are
-;; over ridable, but more will be added as the need is discovered.
+;; function overrides. At the moment very few functions may be
+;; overridden, but more will be added as the need is discovered.
;;; TODO:
;; - More functions to create buttons and options
;; - Timeout directories we haven't visited in a while.
+;;; Code:
+
(require 'assoc)
(require 'easymenu)
;; customization stuff
(defgroup speedbar nil
"File and tag browser frame."
- :group 'tags
+ :group 'etags
:group 'tools
:group 'convenience
:version "20.3")
:prefix "speedbar-"
:group 'speedbar)
-;;; Code:
(defvar speedbar-initial-expansion-mode-alist
'(("buffers" speedbar-buffer-easymenu-definition speedbar-buffers-key-map
speedbar-buffer-buttons)
(defvar speedbar-special-mode-key-map nil
"Default keymap used when identifying a specialized display mode.
This keymap is local to each buffer that wants to define special keybindings
-effective when it's display is shown.")
+effective when its display is shown.")
(defcustom speedbar-visiting-file-hook nil
"Hooks run when speedbar visits a file in the selected frame."
(width . 20)
(border-width . 0)
(menu-bar-lines . 0)
+ (tool-bar-lines . 0)
(unsplittable . t))
"*Parameters to use when creating the speedbar frame in Emacs.
Any parameter supported by a frame may be added. The parameter `height'
will be initialized to the height of the frame speedbar is
attached to and added to this list before the new frame is initialized."
:group 'speedbar
- :type '(repeat (sexp :tag "Parameter:")))
+ :type '(repeat (cons :format "%v"
+ (symbol :tag "Parameter")
+ (sexp :tag "Value"))))
;; These values by Hrvoje Niksic <hniksic@srce.hr>
(defcustom speedbar-frame-plist
(symbol :tag "Property")
(sexp :tag "Value"))))
-(defcustom speedbar-use-imenu-flag (stringp (locate-library "imenu"))
+(defcustom speedbar-use-imenu-flag (fboundp 'imenu)
"*Non-nil means use imenu for file parsing. nil to use etags.
XEmacs prior to 20.4 doesn't support imenu, therefore the default is to
use etags instead. Etags support is not as robust as imenu support."
(defvar speedbar-dynamic-tags-function-list
'((speedbar-fetch-dynamic-imenu . speedbar-insert-imenu-list)
(speedbar-fetch-dynamic-etags . speedbar-insert-etags-list))
- "Set to a functions which will return and insert a list of tags.
+ "Set to a list of functions which will return and insert a list of tags.
Each element is of the form ( FETCH . INSERT ) where FETCH
-is a funciotn which takes one parameter (the file to tag) and returns a
+is a function which takes one parameter (the file to tag) and returns a
list of tags. The tag list can be of any form as long as the
corresponding insert method can handle it. If it returns t, then an
-error occured, and the next fetch routine is tried.
+error occurred, and the next fetch routine is tried.
INSERT is a function which takes an INDENTation level, and a LIST of
tags to insert. It will then create the speedbar buttons.")
:type 'boolean)
(defcustom speedbar-sort-tags nil
- "*If Non-nil, sort tags in the speedbar display. *Obsolete*."
+ "*If non-nil, sort tags in the speedbar display. *Obsolete*."
:group 'speedbar
:type 'boolean)
"*List of hooks which speedbar will use to organize tags into groups.
Groups are defined as expandable meta-tags. Imenu supports
such things in some languages, such as separating variables from
-functions. Each hook takes one argument LST, and may destructivly
+functions. Each hook takes one argument LST, and may destructively
create a new list of the same form. LST is a list of elements of the
form:
(ELT1 ELT2 ... ELTn)
where each ELT is of the form
(TAG-NAME-STRING . NUMBER-OR-MARKER)
or
- (GROUP-NAME-STRING ELT1 EL2... ELTn)"
+ (GROUP-NAME-STRING ELT1 ELT2... ELTn)"
:group 'speedbar
:type 'hook
:options '(speedbar-sort-tag-hierarchy
(if (fboundp 'display-graphic-p)
(display-graphic-p)
window-system))
- "*Non nil if speedbar should display icons."
+ "*Non-nil if speedbar should display icons."
:group 'speedbar
:version "21.1"
:type 'boolean)
(defcustom speedbar-vc-do-check t
"*Non-nil check all files in speedbar to see if they have been checked out.
-Any file checked out is marked with `speedbar-vc-indicator'"
+Any file checked out is marked with `speedbar-vc-indicator'."
:group 'speedbar-vc
:type 'boolean)
(defcustom speedbar-obj-do-check t
"*Non-nil check all files in speedbar to see if they have an object file.
Any file checked out is marked with `speedbar-obj-indicator', and the
-marking is based on `speedbar-obj-alist'"
+marking is based on `speedbar-obj-alist'."
:group 'speedbar-vc
:type 'boolean)
"*Regexp matching files we don't want displayed in a speedbar buffer.
It is generated from the variable `completion-ignored-extensions'")
+;; Compiler silencing trick. The real defvar comes later in this file.
+(defvar speedbar-file-regexp)
+
;; this is dangerous to customize, because the defaults will probably
;; change in the future.
(defcustom speedbar-supported-extension-expressions
(append '(".[ch]\\(\\+\\+\\|pp\\|c\\|h\\|xx\\)?" ".tex\\(i\\(nfo\\)?\\)?"
".el" ".emacs" ".l" ".lsp" ".p" ".java" ".f\\(90\\|77\\|or\\)?")
(if speedbar-use-imenu-flag
- '(".ada" ".p[lm]" ".tcl" ".m" ".scm" ".pm" ".py"
+ '(".ada" ".p[lm]" ".tcl" ".m" ".scm" ".pm" ".py" ".g"
;; html is not supported by default, but an imenu tags package
;; is available. Also, html files are nice to be able to see.
".s?html"
:type '(repeat (regexp :tag "Extension Regexp"))
:set (lambda (sym val)
(setq speedbar-supported-extension-expressions val
- speedbar-file-regexp (speedbar-extension-list-to-regex val)))
- )
+ speedbar-file-regexp (speedbar-extension-list-to-regex val))))
(defvar speedbar-file-regexp
(speedbar-extension-list-to-regex speedbar-supported-extension-expressions)
Created from `speedbar-supported-extension-expression' with the
function `speedbar-extension-list-to-regex'")
+(defcustom speedbar-scan-subdirs nil
+ "*Non-nil means speedbar will check if subdirs are empty.
+That way you don't have to click on them to find out. But this
+incurs extra I/O, hence it slows down directory display
+proportionally to the number of subdirs."
+ :group 'speedbar
+ :type 'boolean
+ :version 22.1)
+
(defun speedbar-add-supported-extension (extension)
"Add EXTENSION as a new supported extension for speedbar tagging.
This should start with a `.' if it is not a complete file name, and
the dot should NOT be quoted in with \\. Other regular expression
matchers are allowed however. EXTENSION may be a single string or a
list of strings."
- (interactive "sExtionsion: ")
+ (interactive "sExtension: ")
(if (not (listp extension)) (setq extension (list extension)))
(while extension
(if (member (car extension) speedbar-supported-extension-expressions)
(display-graphic-p)
window-system))
"*Non-nil means to automatically update the display.
-When this is nil then speedbar will not follow the attached frame's path.
-When speedbar is active, use:
-
-\\<speedbar-key-map> `\\[speedbar-toggle-updates]'
-
+When this is nil then speedbar will not follow the attached
+frame's path. Type \
+\\<speedbar-key-map>\\[speedbar-toggle-updates] in the speedbar \
to toggle this value.")
(defvar speedbar-syntax-table nil
))
(defun speedbar-make-specialized-keymap ()
- "Create a keymap for use w/ a speedbar major or minor display mode.
+ "Create a keymap for use with a speedbar major or minor display mode.
This basically creates a sparse keymap, and makes it's parent be
`speedbar-key-map'."
(let ((k (make-sparse-keymap)))
(looking-at "[0-9]+: *\\[[+-]\\] [^ \n]+ \\*?[!#]$"))]
)
"Additional menu items while in file-mode.")
-
+
(defvar speedbar-easymenu-definition-trailer
(append
(if (and (featurep 'custom) (fboundp 'custom-declare-variable))
"Menu items appearing at the end of the speedbar menu.")
(defvar speedbar-desired-buffer nil
- "Non-nil when speedbar is showing buttons specific a special mode.
+ "Non-nil when speedbar is showing buttons specific to a special mode.
In this case it is the originating buffer.")
(defvar speedbar-buffer nil
"The buffer displaying the speedbar.")
(if (fboundp 'frame-parameter)
(defalias 'speedbar-frame-parameter 'frame-parameter)
-
+
(defun speedbar-frame-parameter (frame parameter)
"Return FRAME's PARAMETER value."
(cdr (assoc parameter (frame-parameters frame)))))
which is generated from `completion-ignored-extensions'.
Files with a `*' character after their name are files checked out of a
-version control system. (currently only RCS is supported.) New
+version control system. (Currently only RCS is supported.) New
version control systems can be added by examining the documentation
-for `speedbar-this-file-in-vc' and `speedbar-vc-check-dir-p'
+for `speedbar-this-file-in-vc' and `speedbar-vc-check-dir-p'.
Files with a `#' or `!' character after them are source files that
have an object file associated with them. The `!' indicates that the
-files is out of date. You can control what source/object associations
+files is out of date. You can control what source/object associations
exist through the variable `speedbar-obj-alist'.
Click on the [+] to display a list of tags from that file. Click on
(speedbar-quick-mouse event)))
;; Don't do normal operations.
t)))))
- (make-local-hook 'kill-buffer-hook)
(add-hook 'kill-buffer-hook (lambda () (let ((skilling (boundp 'skilling)))
(if skilling
nil
(toggle-read-only 1)
(speedbar-set-mode-line-format)
(if speedbar-xemacsp
- (set (make-local-variable 'mouse-motion-handler)
- 'speedbar-track-mouse-xemacs)
+ (with-no-warnings
+ (set (make-local-variable 'mouse-motion-handler)
+ 'speedbar-track-mouse-xemacs))
(if speedbar-track-mouse-flag
(set (make-local-variable 'track-mouse) t)) ;this could be messy.
(setq auto-show-mode nil)) ;no auto-show for Emacs
- (run-hooks 'speedbar-mode-hook))
+ (run-mode-hooks 'speedbar-mode-hook))
(speedbar-update-contents)
speedbar-buffer)
(if (equal (car pos) speedbar-frame)
(save-excursion
(save-window-excursion
- (apply 'set-mouse-position pos)
+ (apply 'set-mouse-position (list (car pos) (cadr pos) (cddr pos)))
(speedbar-item-info))))))
(defun speedbar-set-mode-line-format ()
frame and window to be the currently active frame and window."
(if (and (frame-live-p speedbar-frame)
(or (not speedbar-xemacsp)
- (specifier-instance has-modeline-p)))
+ (with-no-warnings
+ (specifier-instance has-modeline-p))))
(save-excursion
(set-buffer speedbar-buffer)
(let* ((w (or (speedbar-frame-width) 20))
(defun speedbar-mouse-hscroll (e)
"Read a mouse event E from the mode line, and horizontally scroll.
If the mouse is being clicked on the far left, or far right of the
-mode-line. This is only useful for non-XEmacs"
+mode-line. This is only useful for non-XEmacs."
(interactive "e")
(let* ((xp (car (nth 2 (car (cdr e)))))
(cpw (/ (frame-pixel-width)
;; This gets the cursor where the user can see it.
(if (not (bolp)) (forward-char -1))
(sit-for 0)
- (if (< emacs-major-version 20)
- (mouse-major-mode-menu e)
- (mouse-major-mode-menu e nil))))
+ (mouse-major-mode-menu e nil)))
(defun speedbar-hack-buffer-menu (e)
"Control mouse 1 is buffer menu.
(defun speedbar-up-directory ()
"Keyboard accelerator for moving the default directory up one.
-Assumes that the current buffer is the speedbar buffer"
+Assumes that the current buffer is the speedbar buffer."
(interactive)
(setq default-directory (expand-file-name (concat default-directory "../")))
(speedbar-update-contents))
"Refresh the current speedbar display, disposing of any cached data."
(interactive)
(let ((dl speedbar-shown-directories)
- (dm (and (boundp 'deactivate-mark) deactivate-mark)))
+ deactivate-mark)
(while dl
(adelete 'speedbar-directory-contents-alist (car dl))
(setq dl (cdr dl)))
;; Reset the timer in case it got really hosed for some reason...
(speedbar-set-timer speedbar-update-speed)
(if (<= 1 speedbar-verbosity-level)
- (speedbar-message "Refreshing speedbar...done"))
- (if (boundp 'deactivate-mark) (setq deactivate-mark dm))))
+ (speedbar-message "Refreshing speedbar...done"))))
(defun speedbar-item-load ()
"Load the item under the cursor or mouse if it is a Lisp file."
(speedbar-item-info))
(defun speedbar-generic-item-info ()
- "Attempt to derive, and then display information about thils line item.
+ "Attempt to derive, and then display information about this line item.
File style information is displayed with `speedbar-item-info'."
(save-excursion
(beginning-of-line)
(defun speedbar-item-info ()
"Display info in the mini-buffer about the button the mouse is over.
This function can be replaced in `speedbar-mode-functions-list' as
-`speedbar-item-info'"
+`speedbar-item-info'."
(interactive)
(let (message-log-max)
(funcall (or (speedbar-fetch-replacement-function 'speedbar-item-info)
(speedbar-enable-update)))
(defun speedbar-toggle-images ()
- "Toggle automatic update for the speedbar frame."
+ "Toggle images for the speedbar frame."
(interactive)
(setq speedbar-use-images (not speedbar-use-images))
(speedbar-refresh))
(defun speedbar-toggle-sorting ()
- "Toggle automatic update for the speedbar frame."
+ "Toggle sorting for the speedbar frame."
(interactive)
(setq speedbar-sort-tags (not speedbar-sort-tags)))
;;; Utility functions
;;
(defun speedbar-set-timer (timeout)
- "Apply a timer with TIMEOUT, or remove a timer if TIMOUT is nil.
+ "Apply a timer with TIMEOUT, or remove a timer if TIMEOUT is nil.
TIMEOUT is the number of seconds until the speedbar timer is called
again. When TIMEOUT is nil, turn off all timeouts.
This function will also enable or disable the `vc-checkin-hook' used
This function assumes that the current buffer is the speedbar buffer.
If PREVLINE, then put this button on the previous line.
-This is a convenience function for special mode that create their own
+This is a convenience function for special modes that create their own
specialized speedbar displays."
(goto-char (point-max))
(let ((start (point)))
(defun speedbar-make-button (start end face mouse function &optional token)
"Create a button from START to END, with FACE as the display face.
MOUSE is the mouse face. When this button is clicked on FUNCTION
-will be run with the TOKEN parameter (any Lisp object)"
+will be run with the TOKEN parameter (any Lisp object)."
(put-text-property start end 'face face)
(put-text-property start end 'mouse-face mouse)
(put-text-property start end 'invisible nil)
The car is the list of directories, the cdr is list of files not
matching ignored headers. Cache any directory files found in
`speedbar-directory-contents-alist' and use that cache before scanning
-the file-system"
+the file-system."
(setq directory (expand-file-name directory))
;; If in powerclick mode, then the directory we are getting
;; should be rescanned.
;; find the directory, either in the cache, or build it.
(or (cdr-safe (assoc directory speedbar-directory-contents-alist))
(let ((default-directory directory)
- (dir (directory-files directory nil))
- (dirs nil)
- (files nil))
- (while dir
- (if (not
- (or (string-match speedbar-file-unshown-regexp (car dir))
- (string-match speedbar-directory-unshown-regexp (car dir))))
- (if (file-directory-p (car dir))
- (setq dirs (cons (car dir) dirs))
- (setq files (cons (car dir) files))))
- (setq dir (cdr dir)))
- (let ((nl (cons (nreverse dirs) (list (nreverse files)))))
+ (case-fold-search read-file-name-completion-ignore-case)
+ dirs files)
+ (dolist (file (directory-files directory nil))
+ (or (string-match speedbar-file-unshown-regexp file)
+ (string-match speedbar-directory-unshown-regexp file)
+ (if (file-directory-p file)
+ (setq dirs (cons file dirs))
+ (setq files (cons file files)))))
+ (let ((nl `(,(nreverse dirs) ,(nreverse files))))
(aput 'speedbar-directory-contents-alist directory nl)
- nl))
- ))
+ nl))))
(defun speedbar-directory-buttons (directory index)
"Insert a single button group at point for DIRECTORY.
Lastly, DEPTH shows the depth of expansion.
This function assumes that the cursor is in the speedbar window at the
-position to insert a new item, and that the new item will end with a CR"
+position to insert a new item, and that the new item will end with a CR."
(let ((start (point))
(end (progn
(insert (int-to-string depth) ":")
(if tag-button-function 'speedbar-highlight-face nil)
tag-button-function tag-button-data))
))
-
+
(defun speedbar-change-expand-button-char (char)
"Change the expansion button character to CHAR for the current line."
(save-excursion
\f
;;; Build button lists
;;
-(defun speedbar-insert-files-at-point (files level)
+(defun speedbar-insert-files-at-point (files level directory)
"Insert list of FILES starting at point, and indenting all files to LEVEL.
Tag expandable items with a +, otherwise a ?. Don't highlight ? as we
don't know how to manage them. The input parameter FILES is a cons
-cell of the form ( 'DIRLIST . 'FILELIST )"
+cell of the form ( 'DIRLIST . 'FILELIST )."
;; Start inserting all the directories
- (let ((dirs (car files)))
- (while dirs
- (speedbar-make-tag-line 'angle ?+ 'speedbar-dired (car dirs)
- (car dirs) 'speedbar-dir-follow nil
- 'speedbar-directory-face level)
- (setq dirs (cdr dirs))))
- (let ((lst (car (cdr files)))
- (case-fold-search t))
- (while lst
- (let* ((known (string-match speedbar-file-regexp (car lst)))
+ (dolist (dir (car files))
+ (if (if speedbar-scan-subdirs
+ (condition-case nil
+ (let ((l (speedbar-file-lists (concat directory dir))))
+ (or (car l) (cadr l)))
+ (file-error))
+ (file-readable-p (concat directory dir)))
+ (speedbar-make-tag-line 'angle ?+ 'speedbar-dired dir
+ dir 'speedbar-dir-follow nil
+ 'speedbar-directory-face level)
+ (speedbar-make-tag-line 'angle ? nil dir
+ dir 'speedbar-dir-follow nil
+ 'speedbar-directory-face level)))
+ (let ((case-fold-search read-file-name-completion-ignore-case))
+ (dolist (file (cadr files))
+ (let* ((known (and (file-readable-p (concat directory file))
+ (string-match speedbar-file-regexp file)))
(expchar (if known ?+ ??))
(fn (if known 'speedbar-tag-file nil)))
(if (or speedbar-show-unknown-files (/= expchar ??))
- (speedbar-make-tag-line 'bracket expchar fn (car lst)
- (car lst) 'speedbar-find-file nil
- 'speedbar-file-face level)))
- (setq lst (cdr lst)))))
+ (speedbar-make-tag-line 'bracket expchar fn file
+ file 'speedbar-find-file nil
+ 'speedbar-file-face level))))))
(defun speedbar-default-directory-list (directory index)
"Insert files for DIRECTORY with level INDEX at point."
(speedbar-insert-files-at-point
- (speedbar-file-lists directory) index)
+ (speedbar-file-lists directory) index directory)
(speedbar-reset-scanners)
(if (= index 0)
;; If the shown files variable has extra directories, then
(if (looking-at "[0-9]+:[ ]*<")
(progn
(goto-char (match-end 0))
- (speedbar-do-function-pointer)))
- (setq sf (cdr sf)))))
+ (speedbar-do-function-pointer)))))
+ (setq sf (cdr sf)))
)))
(defun speedbar-sort-tag-hierarchy (lst)
(speedbar-insert-generic-list indent lst
'speedbar-tag-expand
'speedbar-tag-find))
-
+
(defun speedbar-insert-etags-list (indent lst)
"At level INDENT, insert the etags generated LST."
(speedbar-insert-generic-list indent lst
(speedbar-reconfigure-keymaps))
(defun speedbar-update-special-contents ()
- "Used the mode-specific variable to fill in the speedbar buffer.
+ "Use the mode-specific variable to fill in the speedbar buffer.
This should only be used by modes classified as special."
(let ((funclst speedbar-special-mode-expansion-list)
(specialbuff (current-buffer)))
)
(defun speedbar-find-selected-file (file)
- "Goto the line where FILE is."
+ "Go to the line where FILE is."
(goto-char (point-min))
(let ((m nil))
(while (and (setq m (re-search-forward
- (concat " \\(" (file-name-nondirectory file)
+ (concat " \\(" (regexp-quote (file-name-nondirectory file))
"\\)\\(" speedbar-indicator-regex "\\)?\n")
nil t))
(not (string= file
(newcf (if newcfd newcfd))
(lastb (current-buffer))
(sucf-recursive (boundp 'sucf-recursive))
- (case-fold-search t))
+ (case-fold-search read-file-name-completion-ignore-case))
(if (and newcf
;; check here, that way we won't refresh to newcf until
;; its been written, thus saving ourselves some time
(defun speedbar-add-indicator (indicator-string &optional replace-this)
"Add INDICATOR-STRING to the end of this speedbar line.
If INDICATOR-STRING is space, and REPLACE-THIS is a character, then
-an the existing indicator is removed. If there is already an
+the existing indicator is removed. If there is already an
indicator, then do not add a space."
(beginning-of-line)
;; The nature of the beast: Assume we are in "the right place"
(defun speedbar-do-function-pointer ()
"Look under the cursor and examine the text properties.
From this extract the file/tag name, token, indentation level and call
-a function if appropriate"
+a function if appropriate."
(let* ((fn (get-text-property (point) 'speedbar-function))
(tok (get-text-property (point) 'speedbar-token))
;; The 1-,+ is safe because scaning starts AFTER the point
nil)))
(defun speedbar-line-file (&optional p)
- "Retrieve the file or whatever from the line at P point.
+ "Retrieve the file or whatever from the line at point P.
The return value is a string representing the file. If it is a
directory, then it is the directory name."
(save-match-data
(if f
(let* ((depth (string-to-int (match-string 1)))
(path (speedbar-line-path depth)))
- (concat path f))
+ (if (file-exists-p (concat path f))
+ (concat path f)
+ nil))
nil))))
(defun speedbar-goto-this-file (file)
- "If FILE is displayed, goto this line and return t.
+ "If FILE is displayed, go to this line and return t.
Otherwise do not move and return nil."
(let ((path (substring (file-name-directory (expand-file-name file))
(length (expand-file-name default-directory))))
"Retrieve the pathname associated with the current line.
This may require traversing backwards from DEPTH and combining the default
directory with these items. This function is replaceable in
-`speedbar-mode-functions-list' as `speedbar-line-path'"
+`speedbar-mode-functions-list' as `speedbar-line-path'."
(let ((rf (speedbar-fetch-replacement-function 'speedbar-line-path)))
(if rf (funcall rf depth) default-directory)))
-
+
(defun speedbar-files-line-path (&optional depth)
"Retrieve the pathname associated with the current line.
This may require traversing backwards from DEPTH and combining the default
(if (re-search-forward "[]>?}] [^ ]"
(save-excursion (end-of-line) (point))
t)
- (speedbar-do-function-pointer)
+ (progn
+ (forward-char -1)
+ (speedbar-do-function-pointer))
nil))
(speedbar-do-function-pointer)))
(forward-char -2)
(speedbar-do-function-pointer))
(error (speedbar-position-cursor-on-line)))))
-
+
(defun speedbar-flush-expand-line ()
"Expand the line under the cursor and flush any cached information."
(interactive)
(speedbar-expand-line 1))
-
+
(defun speedbar-contract-line ()
"Contract the line under the cursor."
(interactive)
(if speedbar-xemacsp
(defalias 'speedbar-mouse-event-p 'button-press-event-p)
(defun speedbar-mouse-event-p (event)
- "Return t if the event is a mouse related event"
+ "Return t if the event is a mouse related event."
;; And Emacs does it this way
(if (and (listp event)
(member (event-basic-type event)
(defun speedbar-dir-follow (text token indent)
"Speedbar click handler for directory names.
-Clicking a directory will cause the speedbar to list files in the
+Clicking a directory will cause the speedbar to list files in
the subdirectory TEXT. TOKEN is an unused requirement. The
subdirectory chosen will be at INDENT level."
(setq default-directory
TEXT is the button clicked on. TOKEN is the directory to follow.
INDENT is the current indentation level and is unused."
(if (string-match "^[A-z]:$" token)
- (setq default-directory (concat token (char-to-string directory-sep-char)))
+ (setq default-directory (concat token "/"))
(setq default-directory token))
;; Because we leave speedbar as the current buffer,
;; update contents will change directory without
(speedbar-center-buffer-smartly))
(defun speedbar-tag-find (text token indent)
- "For the tag TEXT in a file TOKEN, goto that position.
+ "For the tag TEXT in a file TOKEN, go to that position.
INDENT is the current indentation level."
(let ((file (speedbar-line-path indent)))
(speedbar-find-file-in-frame file)
nil
-(eval-when-compile (if (locate-library "imenu") (require 'imenu)))
+(eval-when-compile (condition-case nil (require 'imenu) (error nil)))
(defun speedbar-fetch-dynamic-imenu (file)
"Load FILE into a buffer, and generate tags using Imenu.
(defvar speedbar-fetch-etags-command "etags"
"*Command used to create an etags file.
-This variable is ignored if `speedbar-use-imenu-flag' is t")
+This variable is ignored if `speedbar-use-imenu-flag' is t.")
(defvar speedbar-fetch-etags-arguments '("-D" "-I" "-o" "-")
"*List of arguments to use with `speedbar-fetch-etags-command'.
This creates an etags output buffer. Use `speedbar-toggle-etags' to
modify this list conveniently.
-This variable is ignored if `speedbar-use-imenu-flag' is t")
+This variable is ignored if `speedbar-use-imenu-flag' is t.")
(defun speedbar-toggle-etags (flag)
"Toggle FLAG in `speedbar-fetch-etags-arguments'.
`speedbar-show-unknown-files'.
This function is a convenience function for XEmacs menu created by
-Farzin Guilak <farzin@protocol.com>"
+Farzin Guilak <farzin@protocol.com>."
(interactive)
(cond
((equal flag "sort")
(defun speedbar-extract-one-symbol (expr)
"At point, return nil, or one alist in the form: (SYMBOL . POSITION)
The line should contain output from etags. Parse the output using the
-regular expression EXPR"
+regular expression EXPR."
(let* ((sym (if (stringp expr)
(if (save-excursion
(re-search-forward expr (save-excursion
nil)))
(defun speedbar-parse-c-or-c++tag ()
- "Parse a c or c++ tag, which tends to be a little complex."
+ "Parse a C or C++ tag, which tends to be a little complex."
(save-excursion
(let ((bound (save-excursion (end-of-line) (point))))
(cond ((re-search-forward "\C-?\\([^\C-a]+\\)\C-a" bound t)
(defun speedbar-buffers-line-path (&optional depth)
"Fetch the full path to the file (buffer) specified on the current line.
Optional argument DEPTH specifies the current depth of the back search."
- (end-of-line)
- ;; Buffers are always at level 0
- (if (not (re-search-backward "^0:" nil t))
- nil
- (let* ((bn (speedbar-line-text))
- (buffer (if bn (get-buffer bn))))
- (if buffer (file-name-directory (buffer-file-name buffer))))))
+ (save-excursion
+ (end-of-line)
+ (let ((start (point)))
+ ;; Buffers are always at level 0
+ (if (not (re-search-backward "^0:" nil t))
+ nil
+ (let* ((bn (speedbar-line-text))
+ (buffer (if bn (get-buffer bn))))
+ (if buffer
+ (if (save-excursion
+ (end-of-line)
+ (eq start (point)))
+ (file-name-directory (buffer-file-name buffer))
+ (buffer-file-name buffer))))))))
(defun speedbar-buffer-click (text token indent)
"When the users clicks on a buffer-button in speedbar.
)
(defun speedbar-unhighlight-one-tag-line ()
- "Unhighlight the currently highlight line."
+ "Unhighlight the currently highlighted line."
(if speedbar-highlight-one-tag-line
(progn
(speedbar-delete-overlay speedbar-highlight-one-tag-line)
(:foreground "cyan4"))
(((class color) (background dark))
(:foreground "cyan"))
- (t (:bold t)))
+ (t (:weight bold)))
"Face used for file names."
:group 'speedbar-faces)
(:foreground "blue4"))
(((class color) (background dark))
(:foreground "light blue")))
- "Faced used for directory names."
+ "Face used for directory names."
:group 'speedbar-faces)
(defface speedbar-tag-face '((((class color) (background light))
(:foreground "brown"))
(:background "green"))
(((class color) (background dark))
(:background "sea green"))
- (((class grayscale monochrome)
+ (((class grayscale mono)
(background light))
(:background "black"))
- (((class grayscale monochrome)
+ (((class grayscale mono)
(background dark))
(:background "white")))
"Face used for highlighting buttons with the mouse."
(defalias 'defimage-speedbar 'defimage)
(if (not (fboundp 'make-glyph))
-
+
(defmacro defimage-speedbar (variable imagespec docstring)
"Don't bother loading up an image...
-Argument VARIABLE is the varible to define.
+Argument VARIABLE is the variable to define.
Argument IMAGESPEC is the list defining the image to create.
Argument DOCSTRING is the documentation for VARIABLE."
`(defvar ,variable nil ,docstring))
r))
(defun speedbar-convert-emacs21-imagespec-to-xemacs (spec)
- "Convert the Emacs21 Image SPEC into an XEmacs image spec."
+ "Convert the Emacs21 image SPEC into an XEmacs image spec."
(let* ((sl (car spec))
(itype (nth 1 sl))
(ifile (nth 3 sl)))
(vector itype ':file (speedbar-find-image-on-load-path ifile))))
(defmacro defimage-speedbar (variable imagespec docstring)
- "Devine VARIABLE as an image if `defimage' is not available..
+ "Define VARIABLE as an image if `defimage' is not available.
IMAGESPEC is the image data, and DOCSTRING is documentation for the image."
`(defvar ,variable
;; The Emacs21 version of defimage looks just like the XEmacs image
(speedbar-convert-emacs21-imagespec-to-xemacs (quote ,imagespec)))
'buffer)
(error nil))
- ,docstring))
-
-)))
+ ,docstring)))))
(defimage-speedbar speedbar-directory-plus
((:type xpm :file "sb-dir-plus.xpm" :ascent center))
((:type xpm :file "sb-dir-minus.xpm" :ascent center))
"Image used for open directories with stuff in them.")
+(defimage-speedbar speedbar-directory
+ ((:type xpm :file "sb-dir.xpm" :ascent center))
+ "Image used for empty or unreadable directories.")
+
(defimage-speedbar speedbar-page-plus
((:type xpm :file "sb-pg-plus.xpm" :ascent center))
"Image used for closed files with stuff in them.")
(defvar speedbar-expand-image-button-alist
'(("<+>" . speedbar-directory-plus)
("<->" . speedbar-directory-minus)
+ ("< >" . speedbar-directory)
("[+]" . speedbar-page-plus)
("[-]" . speedbar-page-minus)
("[?]" . speedbar-page)
;; underlying text. This means if we leave it tangible, then I
;; don't have to change said giant piles o code.
(if (and a (symbol-value (cdr a)))
- (if (fboundp 'set-extent-property)
+ (if (featurep 'xemacs)
(add-text-properties (+ start (length bt)) start
(list 'end-glyph (symbol-value (cdr a))
'rear-nonsticky (list 'display)
(def-edebug-spec speedbar-with-writable def-body)))
(provide 'speedbar)
-;;; speedbar ends here
;; run load-time hooks
(run-hooks 'speedbar-load-hook)
+
+;; arch-tag: 4477e6d1-f78c-48b9-a503-387d3c9767d5
+;;; speedbar.el ends here