;;; msb.el --- customizable buffer-selection with multiple menus
;; Copyright (C) 1993, 1994, 1995, 1997, 1998, 1999, 2000, 2001, 2002,
-;; 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+;; 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
;; Author: Lars Lindberg <lars.lindberg@home.se>
;; Maintainer: FSF
;; This file is part of GNU Emacs.
-;; GNU Emacs is free software; you can redistribute it and/or modify
+;; GNU Emacs is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; GNU General Public License for more details.
;; 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., 51 Franklin Street, Fifth Floor,
-;; Boston, MA 02110-1301, USA.
+;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
3099
"Other files (%d)")))
-;; msb--many-menus is obsolete
-(defvar msb--many-menus msb--very-many-menus)
-
;;;
;;; Customizable variables
;;;
(msb-menu-bar-update-buffers t)))
(defcustom msb-menu-cond msb--very-many-menus
- "*List of criteria for splitting the mouse buffer menu.
+ "List of criteria for splitting the mouse buffer menu.
The elements in the list should be of this type:
(CONDITION MENU-SORT-KEY MENU-TITLE ITEM-HANDLING-FN ITEM-SORT-FN).
`save-match-data'.
The categories are sorted by MENU-SORT-KEY. Smaller keys are on top.
-nil means don't display this menu.
+A value of nil means don't display this menu.
MENU-TITLE is really a format. If you add %d in it, the %d is
replaced with the number of items in that menu.
-ITEM-HANDLING-FN, is optional. If it is supplied and is a function,
-than it is used for displaying the items in that particular buffer
+ITEM-HANDLING-FN is optional. If it is supplied and is a function,
+then it is used for displaying the items in that particular buffer
menu, otherwise the function pointed out by
`msb-item-handling-function' is used.
-ITEM-SORT-FN, is also optional.
+ITEM-SORT-FN is also optional.
If it is not supplied, the function pointed out by
`msb-item-sort-function' is used.
If it is nil, then no sort takes place and the buffers are presented
:version "20.3")
(defcustom msb-separator-diff 100
- "*Non-nil means use separators.
+ "Non-nil means use separators.
The separators will appear between all menus that have a sorting key
that differs by this value or more."
:type '(choice integer (const nil))
"*The sort key for files sorted by directory.")
(defcustom msb-max-menu-items 15
- "*The maximum number of items in a menu.
+ "The maximum number of items in a menu.
If this variable is set to 15 for instance, then the submenu will be
-split up in minor parts, 15 items each. nil means no limit."
+split up in minor parts, 15 items each. A value of nil means no limit."
:type '(choice integer (const nil))
:set 'msb-custom-set
:group 'msb)
(defcustom msb-max-file-menu-items 10
- "*The maximum number of items from different directories.
+ "The maximum number of items from different directories.
When the menu is of type `file by directory', this is the maximum
number of buffers that are clumped together from different
:group 'msb)
(defcustom msb-most-recently-used-sort-key -1010
- "*Where should the menu with the most recently used buffers be placed?"
+ "Where should the menu with the most recently used buffers be placed?"
:type 'integer
:set 'msb-custom-set
:group 'msb)
(defcustom msb-display-most-recently-used 15
- "*How many buffers should be in the most-recently-used menu.
+ "How many buffers should be in the most-recently-used menu.
No buffers at all if less than 1 or nil (or any non-number)."
:type 'integer
:set 'msb-custom-set
:group 'msb)
(defcustom msb-most-recently-used-title "Most recently used (%d)"
- "*The title for the most-recently-used menu."
+ "The title for the most-recently-used menu."
:type 'string
:set 'msb-custom-set
:group 'msb)
"*Function that specifies how many pixels to shift the top menu leftwards.")
(defcustom msb-display-invisible-buffers-p nil
- "*Show invisible buffers or not.
+ "Show invisible buffers or not.
Non-nil means that the buffer menu should include buffers that have
names that starts with a space character."
:type 'boolean
"*The appearance of a buffer menu.
The default function to call for handling the appearance of a menu
-item. It should take to arguments, BUFFER and MAX-BUFFER-NAME-LENGTH,
+item. It should take two arguments, BUFFER and MAX-BUFFER-NAME-LENGTH,
where the latter is the max length of all buffer names.
The function should return the string to use in the menu.
information.")
(defcustom msb-item-sort-function 'msb-sort-by-name
- "*The order of items in a buffer menu.
+ "The order of items in a buffer menu.
The default function to call for handling the order of items in a menu
item. This function is called like a sort function. The items look
:group 'msb)
(defcustom msb-files-by-directory nil
- "*Non-nil means that files should be sorted by directory.
+ "Non-nil means that files should be sorted by directory.
This is instead of the groups in `msb-menu-cond'."
:type 'boolean
:set 'msb-custom-set
(defun msb-sort-by-directory (item1 item2)
"Sort the items ITEM1 and ITEM2 by directory name. Made for dired.
An item look like (NAME . BUFFER)."
- (string-lessp (save-excursion (set-buffer (cdr item1))
- (msb--dired-directory))
- (save-excursion (set-buffer (cdr item2))
- (msb--dired-directory))))
+ (string-lessp (with-current-buffer (cdr item1)
+ (msb--dired-directory))
+ (with-current-buffer (cdr item2)
+ (msb--dired-directory))))
;;;
;;; msb
See the function `mouse-select-buffer' and the variable
`msb-menu-cond' for more information about how the menus are split."
(interactive "e")
- ;; If EVENT is a down-event, read and discard the
- ;; corresponding up-event.
- (and (eventp event)
- (memq 'down (event-modifiers event))
- (read-event))
(let ((old-window (selected-window))
- (window (posn-window (event-start event))))
+ (window (posn-window (event-start event)))
+ early-release)
(unless (framep window) (select-window window))
+ ;; This `sit-for' magically makes the menu stay up if the mouse
+ ;; button is released within 0.1 second.
+ (setq early-release (not (sit-for 0.1 t)))
(let ((buffer (mouse-select-buffer event)))
(if buffer
(switch-to-buffer buffer)
- (select-window old-window))))
+ (select-window old-window)))
+ ;; If the above `sit-for' was interrupted by a mouse-up, avoid
+ ;; generating a drag event.
+ (if (and early-release (memq 'down (event-modifiers last-input-event)))
+ (discard-input)))
nil)
;;;
(while rest
(let ((found-p nil)
(tmp-rest rest)
- result
- new-dir item)
+ item)
(setq item (car tmp-rest))
;; Clump together the "rest"-buffers that have a dir that is
;; a subdir of the current one.
(defun msb--create-function-info (menu-cond-elt)
"Create a vector from an element MENU-COND-ELT of `msb-menu-cond'.
This takes the form:
-\]BUFFER-LIST-VARIABLE CONDITION MENU-SORT-KEY MENU-TITLE ITEM-HANDLER SORTER)
+\[BUFFER-LIST-VARIABLE CONDITION MENU-SORT-KEY MENU-TITLE ITEM-HANDLER SORTER]
See `msb-menu-cond' for a description of its elements."
(let* ((list-symbol (make-symbol "-msb-buffer-list"))
(tmp-ih (and (> (length menu-cond-elt) 3)
(defun msb--add-to-menu (buffer function-info max-buffer-name-length)
"Add BUFFER to the menu depicted by FUNCTION-INFO.
All side-effects. Adds an element of form (BUFFER-TITLE . BUFFER)
-to the buffer-list variable in function-info."
+to the buffer-list variable in FUNCTION-INFO."
(let ((list-symbol (aref function-info 0))) ;BUFFER-LIST-VARIABLE
;; Here comes the hairy side-effect!
(set list-symbol
(unless (and (not msb-display-invisible-buffers-p)
(msb-invisible-buffer-p buffer))
(condition-case nil
- (save-excursion
- (set-buffer buffer)
+ (with-current-buffer buffer
;; Menu found. Add to this menu
(dolist (info (msb--collect function-info-vector))
(msb--add-to-menu buffer info max-buffer-name-length)))
results in
\((a a1 a2 a4 a3) (b b1 b3 b2) (c c3))"
(when (not (null alist))
- (let (result
- same
+ (let (same
tmp-old-car
tmp-same
(first-time-p t)
old-car (car item))
(list (cons tmp-old-car (nreverse tmp-same))))))
(sort alist (lambda (item1 item2)
- (funcall sort-predicate (car item1) (car item2))))))
+ (funcall sort-predicate
+ (car item1) (car item2))))))
(list (cons old-car (nreverse same)))))))
(sort
(let ((mode-list nil))
(dolist (buffer (cdr (buffer-list)))
- (save-excursion
- (set-buffer buffer)
+ (with-current-buffer buffer
(when (and (not (msb-invisible-buffer-p))
(not (assq major-mode mode-list)))
- (push (cons major-mode mode-name)
+ (push (cons major-mode
+ (format-mode-line mode-name nil nil buffer))
mode-list))))
mode-list)
(lambda (item1 item2)
(most-recently-used
(loop with n = 0
for buffer in buffers
- if (save-excursion
- (set-buffer buffer)
+ if (with-current-buffer buffer
(and (not (msb-invisible-buffer-p))
(not (eq major-mode 'dired-mode))))
- collect (save-excursion
- (set-buffer buffer)
+ collect (with-current-buffer buffer
(cons (funcall msb-item-handling-function
buffer
max-buffer-name-length)
(when file-buffers
(setq file-buffers
(mapcar (lambda (buffer-list)
- (cons msb-files-by-directory-sort-key
- (cons (car buffer-list)
- (sort
- (mapcar (function
- (lambda (buffer)
- (cons (save-excursion
- (set-buffer buffer)
- (funcall msb-item-handling-function
- buffer
- max-buffer-name-length))
- buffer)))
- (cdr buffer-list))
- (function
- (lambda (item1 item2)
- (string< (car item1) (car item2))))))))
- (msb--choose-file-menu file-buffers))))
+ (list* msb-files-by-directory-sort-key
+ (car buffer-list)
+ (sort
+ (mapcar (lambda (buffer)
+ (cons (with-current-buffer buffer
+ (funcall
+ msb-item-handling-function
+ buffer
+ max-buffer-name-length))
+ buffer))
+ (cdr buffer-list))
+ (lambda (item1 item2)
+ (string< (car item1) (car item2))))))
+ (msb--choose-file-menu file-buffers))))
;; Now make the menu - a list of (TITLE . BUFFER-LIST)
(let* (menu
(most-recently-used
"*Files by directory*")
'msb--toggle-menu-type)))))))
-(defun msb--create-buffer-menu ()
+(defun msb--create-buffer-menu ()
(save-match-data
(save-excursion
(msb--create-buffer-menu-2))))
(defun msb--toggle-menu-type ()
- "Multi purpose function for selecting a buffer with the mouse."
+ "Multi-purpose function for selecting a buffer with the mouse."
(interactive)
(setq msb-files-by-directory (not msb-files-by-directory))
;; This gets a warning, but it is correct,
;; adjust position
(setq posX (- posX (funcall msb-horizontal-shift-function))
position (list (list posX posY) posWind))))
- ;; This `sit-for' magically makes the menu stay up if the mouse
- ;; button is released within 0.1 second.
- (sit-for 0 100)
;; Popup the menu
(setq choice (x-popup-menu position msb--last-buffer-menu))
(cond
buffers-menu frames-menu)
;; Make the menu of buffers proper.
(setq msb--last-buffer-menu (msb--create-buffer-menu))
- (setq buffers-menu msb--last-buffer-menu)
+ ;; Skip the `keymap' symbol.
+ (setq buffers-menu (cdr msb--last-buffer-menu))
;; Make a Frames menu if we have more than one frame.
(when (cdr frames)
(let* ((frame-length (length frames))
(f-title (format "Frames (%d)" frame-length)))
;; List only the N most recently selected frames
(when (and (integerp msb-max-menu-items)
- (> msb-max-menu-items 1)
+ (> msb-max-menu-items 1)
(> frame-length msb-max-menu-items))
(setcdr (nthcdr msb-max-menu-items frames) nil))
(setq frames-menu
(cons nil nil))
'menu-bar-select-frame))
frames)))))
- (define-key (current-global-map) [menu-bar buffer]
- (cons "Buffers"
+ (setcdr global-buffers-menu-map
(if (and buffers-menu frames-menu)
;; Combine Frame and Buffers menus with separator between
- (nconc (list 'keymap "Buffers and Frames" frames-menu
+ (nconc (list "Buffers and Frames" frames-menu
(and msb-separator-diff '(separator "--")))
- (cddr buffers-menu))
- (or buffers-menu 'undefined)))))))
+ (cdr buffers-menu))
+ buffers-menu)))))
;; Snarf current bindings of `mouse-buffer-menu' (normally
;; C-down-mouse-1).
(add-hook 'menu-bar-update-hook 'menu-bar-update-buffers)
(menu-bar-update-buffers t)))
-(defun msb-unload-hook ()
- (msb-mode 0))
-(add-hook 'msb-unload-hook 'msb-unload-hook)
+(defun msb-unload-function ()
+ "Unload the Msb library."
+ (msb-mode -1)
+ ;; continue standard unloading
+ nil)
(provide 'msb)
(eval-after-load "msb" '(run-hooks 'msb-after-load-hook 'msb-after-load-hooks))
-;;; arch-tag: 403f9e82-b92e-4e7a-a797-5d6d9b76da36
+;; arch-tag: 403f9e82-b92e-4e7a-a797-5d6d9b76da36
;;; msb.el ends here