;;; msb.el --- Customizable buffer-selection with multiple menus.
-;; Copyright (C) 1993, 1994 Lars Lindberg <Lars.Lindberg@sypro.cap.se>
-;;
+
+;; Copyright (C) 1993, 1994, 1995 Lars Lindberg <Lars.Lindberg@sypro.cap.se>
+
;; Author: Lars Lindberg <Lars.Lindberg@sypro.cap.se>
;; Created: 8 Oct 1993
-;; Lindberg's last update version: 3.28
+;; Lindberg's last update version: 3.31
;; Keywords: mouse buffer menu
-;;
-;; This program is free software; you can redistribute it and/or modify
+
+;; This file is part of GNU Emacs.
+
+;; 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 of the License, or
-;; (at your option) any later version.
-;;
-;; This program is distributed in the hope that it will be useful,
+;; the Free Software Foundation; either version 2, 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
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
-;;
+
;; You should have received a copy of the GNU General Public License
-;; along with this program; if not, write to the Free Software
-;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+;; 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.
;;; Commentary:
-;;
+
;; Purpose of this package:
;; 1. Offer a function for letting the user choose buffer,
;; not necessarily for switching to it.
;; 2. Make a better mouse-buffer-menu.
;;
;; Installation:
-;; (require 'msb)
-;; Note! You now use msb instead of mouse-buffer-menu.
-;;
-;; Now try the menu bar Buffers menu.
+
+;; 1. Byte compile msb first. It uses things in the cl package that
+;; are slow if not compiled, but blazingly fast when compiled. I
+;; have also had one report that said that msb malfunctioned when
+;; not compiled.
+;; 2. (require 'msb)
+;; Note! You now use msb instead of mouse-buffer-menu.
+;; 3. Now try the menu bar Buffers menu.
;;
;; Customization:
;; Look at the variable `msb-menu-cond' for deciding what menus you
;; Known bugs:
;; - Files-by-directory
-;; + No possibility to show client/changed buffers separately
+;; + No possibility to show client/changed buffers separately.
+;; + All file buffers only appear in in a file sub-menu, they will
+;; for instance not appear in the Mail sub-menu.
+
;; Future enhancements:
-;; - [Mattes] had a suggestion about sorting files by extension.
-;; I (Lars Lindberg) think this case could be solved if msb.el was
-;; rewritten to handle more dynamic splitting. It's now completely
-;; static, depending on the menu-cond. If the splitting could also
-;; be done by a user-defined function a lot of cases would be
-;; solved.
-;; - [Jim] suggested that the Frame menu became a part of the buffer menu.
;;; Thanks goes to
-;; [msb] - Mark Brader <msb@sq.com>
-;; [Chalupsky] - Hans Chalupsky <hans@cs.Buffalo.EDU>
-;; [jim] - Jim Berry <m1jhb00@FRB.GOV>
-;; [larry] - Larry Rosenberg <ljr@ictv.com>
-;; [will] - Will Henney <will@astroscu.unam.mx>
-;; [jaalto] - Jari Aalto <jaalto@tre.tele.nokia.fi>
-;; [kifer] - Michael Kifer <kifer@sbkifer.cs.sunysb.edu>
-;; [Gael] - Gael Marziou <gael@gnlab030.grenoble.hp.com>
-;; [Gillespie] - Dave Gillespie <daveg@thymus.synaptics.com>
-;; [Alon] - Alon Albert <alon@milcse.rtsg.mot.com>
-;; [KevinB] - Kevin Broadey, <KevinB@bartley.demon.co.uk>
-;; [Ake] - Ake Stenhof <ake@cadpoint.se>
-;; [RMS] - Richard Stallman <rms@gnu.ai.mit.edu>
-;; [Fisk] - Steve Fisk <fisk@medved.bowdoin.edu>
+;; Mark Brader <msb@sq.com>
+;; Jim Berry <m1jhb00@FRB.GOV>
+;; Hans Chalupsky <hans@cs.Buffalo.EDU>
+;; Larry Rosenberg <ljr@ictv.com>
+;; Will Henney <will@astroscu.unam.mx>
+;; Jari Aalto <jaalto@tre.tele.nokia.fi>
+;; Michael Kifer <kifer@sbkifer.cs.sunysb.edu>
+;; Gael Marziou <gael@gnlab030.grenoble.hp.com>
+;; Dave Gillespie <daveg@thymus.synaptics.com>
+;; Alon Albert <alon@milcse.rtsg.mot.com>
+;; Kevin Broadey, <KevinB@bartley.demon.co.uk>
+;; Ake Stenhof <ake@cadpoint.se>
+;; Richard Stallman <rms@gnu.ai.mit.edu>
+;; Steve Fisk <fisk@medved.bowdoin.edu>
;;; Code:
((eq major-mode 'w3-mode)
4020
"WWW (%d)")
- ((or (memq major-mode '(rmail-mode vm-summary-mode vm-mode mail-mode))
+ ((or (memq major-mode '(rmail-mode rmail-edit-mode vm-summary-mode vm-mode mail-mode))
(memq major-mode '(mh-letter-mode
mh-show-mode
mh-folder-mode))
((eq major-mode 'w3-mode)
4020
"WWW (%d)")
- ((or (memq major-mode '(rmail-mode vm-summary-mode vm-mode mail-mode))
+ ((or (memq major-mode '(rmail-mode rmail-edit-mode vm-summary-mode vm-mode mail-mode))
(memq major-mode '(mh-letter-mode
mh-show-mode
mh-folder-mode))
"*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 togehter from different
+number of buffers that are clumped together from different
directories.
Set this to 1 if you want one menu per directory instead of clumping
the groups in msb-menu-cond.")
(defvar msb-menu-cond msb--very-many-menus
- "*List of criterias 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).
When making the split, the buffers are tested one by one against the
CONDITION, just like a lisp cond: When hitting a true condition, the
-other criterias are *not* tested and the buffer name will appear in
+other criteria are *not* tested and the buffer name will appear in
the menu with the menu-title corresponding to the true condition.
If the condition returns the symbol `multi', then the buffer will be
See the function `mouse-select-buffer' and the variable
`msb-menu-cond' for more information about how the menus are split."
(interactive "e")
- (let ((buffer (mouse-select-buffer event))
+ (let ((old-window (selected-window))
(window (posn-window (event-start event))))
- (when buffer
- (unless (framep window) (select-window window))
- (switch-to-buffer buffer)))
+ (unless (framep window) (select-window window))
+ (let ((buffer (mouse-select-buffer event)))
+ (if buffer
+ (switch-to-buffer buffer)
+ (select-window old-window))))
nil)
;;;
(and (> (length (buffer-name buffer)) 0)
(eq ?\ (aref (buffer-name buffer) 0))))
-;; Strip one hierarcy level from the end of PATH.
+;; Strip one hierarchy level from the end of PATH.
(defun msb--strip-path (path)
(save-match-data
(if (string-match "\\(.+\\)/[^/]+$" path)
(format
"In msb-menu-cond, error for buffer `%s'."
(buffer-name buffer)))
- (error msb--error))))))
+ (error "%s" msb--error))))))
;; Return (SORT-KEY TITLE . BUFFER-LIST) or nil if the
;; buffer-list is empty.
(defun msb--most-recently-used-menu (max-buffer-name-length)
(when (and (numberp msb-display-most-recently-used)
(> msb-display-most-recently-used 0))
- (let* ((most-recently-used
+ (let* ((buffers (cdr (buffer-list)))
+ (most-recently-used
(loop with n = 0
- for buffer in (cdr (buffer-list))
+ for buffer in buffers
if (save-excursion
(set-buffer buffer)
(and (not (msb-invisible-buffer-p))
;; 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
((eq (car choice) 'toggle)
(or (not (fboundp 'frame-or-buffer-changed-p))
(frame-or-buffer-changed-p)
arg))
- (let ((buffers (buffer-list))
- (frames (frame-list))
+ (let ((frames (frame-list))
buffers-menu frames-menu)
- ;; If requested, list only the N most recently selected buffers.
- (when (and (integerp buffers-menu-max-size)
- (> buffers-menu-max-size 1)
- (> (length buffers) buffers-menu-max-size))
- (setcdr (nthcdr buffers-menu-max-size buffers) nil))
;; Make the menu of buffers proper.
(setq msb--last-buffer-menu (msb--create-buffer-menu))
(setq buffers-menu msb--last-buffer-menu)
;; Make a Frames menu if we have more than one frame.
- (if (cdr frames)
+ (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)
+ (> frame-length msb-max-menu-items))
+ (setcdr (nthcdr msb-max-menu-items frames) nil))
(setq frames-menu
- (cons "Select Frame"
- (mapcar
- (function
- (lambda (frame)
- (nconc
- (list frame
- (cdr (assq 'name
- (frame-parameters frame)))
- (cons nil nil))
- 'menu-bar-select-frame)))
- frames))))
- (when frames-menu
- (setq frames-menu (cons 'keymap frames-menu)))
+ (nconc
+ (list 'frame f-title '(nil) 'keymap f-title)
+ (mapcar
+ (function
+ (lambda (frame)
+ (nconc
+ (list frame
+ (cdr (assq 'name
+ (frame-parameters frame)))
+ (cons nil nil))
+ 'menu-bar-select-frame)))
+ frames)))))
(define-key (current-global-map) [menu-bar buffer]
(cons "Buffers"
(if (and buffers-menu frames-menu)
- (list 'keymap "Buffers and Frames"
- (cons 'buffers (cons "Buffers" buffers-menu))
- (cons 'frames (cons "Frames" frames-menu)))
- (or buffers-menu frames-menu 'undefined)))))))
-
-(when (and (boundp 'menu-bar-update-hook)
- (not (fboundp 'frame-or-buffer-changed-p)))
- (defvar msb--buffer-count 0)
- (defun frame-or-buffer-changed-p ()
- (let ((count (length (buffer-list))))
- (when (/= count msb--buffer-count)
- (setq msb--buffer-count count)
- t))))
+ ;; Combine Frame and Buffers menus with separator between
+ (nconc (list 'keymap "Buffers and Frames" frames-menu
+ (and msb-separator-diff '(separator "---")))
+ (cddr buffers-menu))
+ (or buffers-menu 'undefined)))))))
(unless (or (not (boundp 'menu-bar-update-hook))
(memq 'menu-bar-update-buffers menu-bar-update-hook))
(provide 'msb)
(eval-after-load 'msb (run-hooks 'msb-after-load-hooks))
+
+;; Load the cl-extra library now, since we will certainly need it later.
+(mapc 'ignore nil)
+
;;; msb.el ends here