(speedbar-scan-subdirs): New option.
[bpt/emacs.git] / lisp / speedbar.el
index 1ef7bde..0556af4 100644 (file)
 ;; customization stuff
 (defgroup speedbar nil
   "File and tag browser frame."
-  :group 'tags
+  :group 'etags
   :group 'tools
   :group 'convenience
   :version "20.3")
@@ -689,8 +689,16 @@ file."
   :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))))
+
+(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 21.4)
 
 (defvar speedbar-file-regexp
   (speedbar-extension-list-to-regex speedbar-supported-extension-expressions)
@@ -932,7 +940,7 @@ This basically creates a sparse keymap, and makes it's parent be
                     (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))
@@ -981,7 +989,7 @@ directories.")
 (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)))))
@@ -1215,13 +1223,13 @@ Files are completely ignored if they match `speedbar-file-unshown-regexp'
 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
@@ -1676,7 +1684,7 @@ Assumes that the current buffer is the speedbar buffer."
   "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)))
@@ -1687,8 +1695,7 @@ Assumes that the current buffer is the speedbar buffer."
     ;; 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."
@@ -2186,21 +2193,17 @@ the file-system."
   ;; 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.
@@ -2326,7 +2329,7 @@ position to insert a new item, and that the new item will end with a CR."
                            (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
@@ -2344,34 +2347,40 @@ position to insert a new item, and that the new item will end with a CR."
 \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 )."
   ;; 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
@@ -2640,7 +2649,7 @@ name will have the function FIND-FUN and not token."
   (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
@@ -2919,7 +2928,7 @@ updated."
         (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
@@ -3344,7 +3353,7 @@ directory with these items.  This function is replaceable in
 `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
@@ -3411,7 +3420,9 @@ directory with these items."
        (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)))
 
@@ -3428,12 +3439,12 @@ With universal argument ARG, flush cached data."
          (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)
@@ -3554,7 +3565,7 @@ expanded.  INDENT is the current indentation level."
 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
@@ -4175,10 +4186,10 @@ TEXT is the buffer's name, TOKEN and INDENT are unused."
                                    (: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."
@@ -4195,7 +4206,7 @@ TEXT is the buffer's name, TOKEN and INDENT are unused."
     (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 variable to define.
@@ -4234,9 +4245,7 @@ IMAGESPEC is the image data, and DOCSTRING is documentation for the 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))
@@ -4246,6 +4255,10 @@ IMAGESPEC is the image data, and DOCSTRING is documentation for the image."
   ((: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.")
@@ -4289,6 +4302,7 @@ IMAGESPEC is the image data, and DOCSTRING is documentation for the image."
 (defvar speedbar-expand-image-button-alist
   '(("<+>" . speedbar-directory-plus)
     ("<->" . speedbar-directory-minus)
+    ("< >" . speedbar-directory)
     ("[+]" . speedbar-page-plus)
     ("[-]" . speedbar-page-minus)
     ("[?]" . speedbar-page)
@@ -4340,4 +4354,5 @@ If we have an image associated with it, use that image."
 ;; run load-time hooks
 (run-hooks 'speedbar-load-hook)
 
+;;; arch-tag: 4477e6d1-f78c-48b9-a503-387d3c9767d5
 ;;; speedbar.el ends here