;; http://www.dina.kvl.dk/~abraham/custom/
;; custom is available in all versions of Emacs version 20 or better.
;;
+;;; Developing for speedbar
+;;
+;; Adding a speedbar specialized display mode:
+;;
+;; Speedbar can be configured to create a special display for certain
+;; 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.
+;;
+;; If your `major-mode' is `foo-mode', the only requirement is to
+;; create a function called `foo-speedbar-buttons' which takes one
+;; argument, BUFFER. BUFFER will be the buffer speedbar wants filled.
+;; In `foo-speedbar-buttons' there are several functions that make
+;; building a speedbar display easy. See the documentation for
+;; `speedbar-with-writable' (needed because the buffer is usually
+;; read-only) `speedbar-make-tag-line', `speedbar-insert-button', and
+;; `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 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
+;; symbol that is the function to call when clicked on. The "token"
+;; is extra data you can pass along. The "function" must take three
+;; parameters. They are (TEXT TOKEN INDENT). TEXT is the text of the
+;; button clicked on. TOKEN is the data passed in when you create the
+;; button. INDENT is an indentation level, or 0. You can store
+;; indentation levels with `speedbar-make-tag-line' which creates a
+;; line with an expander (eg. [+]) and a text button.
+;;
+;; Some useful functions when writing expand functions, and click
+;; 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 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
+;; `foo-mode', create a variable `foo-speedbar-menu-items'. This
+;; should be a list compatible with the `easymenu' package. It will
+;; be spliced into the main menu. (Available with click-mouse-3). If
+;; you wish to have extra key bindings in your special mode, create a
+;; variable `foo-speedbar-key-map'. Instead of using `make-keymap',
+;; or `make-sparse-keymap', use the function
+;; `speedbar-make-specialized-keymap'. This lets you inherit all of
+;; speedbar's default bindings with low overhead.
+;;
+;; Adding a speedbar top-level display mode:
+;;
+;; Unlike the specialized modes, there are no name requirements,
+;; however the methods for writing a button display, menu, and keymap
+;; are the same. Once you create these items, you can call the
+;; function `speedbar-add-expansion-list'. It takes one parameter
+;; which is a list element of the form (NAME MENU KEYMAP &rest
+;; BUTTON-FUNCTIONS). NAME is a string that will show up in the
+;; Displays menu item. MENU is a symbol containing the menu items to
+;; 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 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.
;;; TODO:
;; - Timeout directories we haven't visited in a while.
:type 'hook)
(defcustom speedbar-after-create-hook '(speedbar-frame-reposition-smartly)
- "*Hooks called before popping up the speedbar frame."
+ "*Hooks called after popping up the speedbar frame."
:group 'speedbar
:type 'hook)
(if (and (featurep 'custom) (fboundp 'custom-declare-variable))
(list ["Customize..." speedbar-customize t]))
(list
- ["Detach" speedbar-detach (and speedbar-frame
- (eq (selected-frame) speedbar-frame)) ]
["Close" dframe-close-frame t]
["Quit" delete-frame t] ))
"Menu items appearing at the end of the speedbar menu.")
(dframe-attached-frame speedbar-frame)
speedbar-default-position))))
-(defun speedbar-detach ()
- "Detach the current Speedbar from auto-updating.
-Doing this allows the creation of a second speedbar."
- (interactive)
- (let ((buffer speedbar-buffer))
- (dframe-detach 'speedbar-frame 'speedbar-cached-frame 'speedbar-buffer)
- (save-excursion
- (set-buffer buffer)
- ;; Permanently disable auto-updating in this speedbar buffer.
- (set (make-local-variable 'speedbar-update-flag) nil)
- (set (make-local-variable 'speedbar-update-flag-disable) t)
- ;; Make local copies of all the different variables to prevent
- ;; funny stuff later...
- )))
-
(defsubst speedbar-current-frame ()
"Return the frame to use for speedbar based on current context."
(dframe-current-frame 'speedbar-frame 'speedbar-mode))
(speedbar-initial-menu)
(save-excursion
(dframe-select-attached-frame speedbar-frame)
- (if (local-variable-p
- 'speedbar-easymenu-definition-special
- (current-buffer))
- ;; If bound locally, we can use it
- speedbar-easymenu-definition-special)))
+ (eval (nth 1 (assoc speedbar-initial-expansion-list-name
+ speedbar-initial-expansion-mode-alist)))))
;; Dynamic menu stuff
'("-")
(list (cons "Displays"
default-directory)
(speedbar-message nil))))
;; Else, we can do a short cut. No text cache.
- (let ((cbd (expand-file-name default-directory))
- )
+ (let ((cbd (expand-file-name default-directory)))
(set-buffer speedbar-buffer)
(speedbar-with-writable
(let* ((window (get-buffer-window speedbar-buffer 0))
- (p (window-point window)))
+ (p (window-point window))
+ (start (window-start window)))
(erase-buffer)
(dolist (func funclst)
(setq default-directory cbd)
(funcall func cbd 0))
(speedbar-reconfigure-keymaps)
- (set-window-point window p)))
- ))))
+ (set-window-point window p)
+ (set-window-start window start)))))))
(defun speedbar-update-directory-contents ()
"Update the contents of the speedbar buffer based on the current directory."
-
- (save-excursion
-
(let ((cbd (expand-file-name default-directory))
cbd-parent
(funclst (speedbar-initial-expansion-list))
(speedbar-directory-line cbd))
;; Open it.
(speedbar-expand-line)
- (erase-buffer)
- (cond (use-cache
- (setq default-directory
- (nth (1- (length speedbar-shown-directories))
- speedbar-shown-directories))
- (insert (cdr cache)))
- (t
- (dolist (func funclst)
- (setq default-directory cbd)
- (funcall func cbd 0)))))
- (goto-char (point-min)))))
+ (let* ((window (get-buffer-window speedbar-buffer 0))
+ (p (window-point window))
+ (start (window-start window)))
+ (erase-buffer)
+ (cond (use-cache
+ (setq default-directory
+ (nth (1- (length speedbar-shown-directories))
+ speedbar-shown-directories))
+ (insert (cdr cache)))
+ (t
+ (dolist (func funclst)
+ (setq default-directory cbd)
+ (funcall func cbd 0))))
+ (set-window-point window p)
+ (set-window-start window start)))))
(speedbar-reconfigure-keymaps))
(defun speedbar-update-special-contents ()
(dolist (func funclst)
;; We do not erase the buffer because these functions may
;; decide NOT to update themselves.
- (funcall func specialbuff)))
- (goto-char (point-min))))
+ (funcall func specialbuff)))))
(speedbar-reconfigure-keymaps))
(defun speedbar-set-timer (timeout)
(frame-visible-p (speedbar-current-frame))
(not (eq (frame-visible-p (speedbar-current-frame)) 'icon)))
(let ((af (selected-frame)))
- (save-window-excursion
(dframe-select-attached-frame speedbar-frame)
;; make sure we at least choose a window to
;; get a good directory from
"Updating speedbar to special mode: %s...done"
major-mode)
(speedbar-message nil))))
- ;; Update all the contents if directories change!
- (if (or (member major-mode speedbar-ignored-modes)
- (eq af (speedbar-current-frame))
- (not (buffer-file-name)))
- nil
- (speedbar-update-localized-contents)
- ))
- (select-frame af)))
+ (speedbar-update-localized-contents))
+ (select-frame af))
;; Now run stealthy updates of time-consuming items
(speedbar-stealthy-updates)))))
(run-hooks 'speedbar-timer-hook))