Download
(eval-when-compile (require 'cl))
(require 'misc-fns nil t)
(require 'misc-cmds nil t)
(require 'fit-frame nil t)
(defvar Buffer-menu-buffer+size-width)
(defvar Buffer-menu-file-flag)
(defvar Buffer-menu-files-only)
(defvar Buffer-menu-mode-flag)
(defvar Buffer-menu-mode-width)
(defvar Buffer-menu-sort-column)
(defvar Buffer-menu-sort-button-map)
(defvar Buffer-menu-time-flag)
(defvar Buffer-menu-time-format)
(defvar Buffer-menu-use-frame-buffer-list)
(defvar Buffer-menu-use-header-line)
(defvar frame-bufs-mode)
(defvar frame-bufs-full-list)
(defvar header-line-format)
(defvar Info-current-file)
(defvar Info-current-node)
(unless (> emacs-major-version 21)
(defgroup Buffer-Menu-Plus nil
"Enhancements to the buffer menu."
:link `(url-link :tag "Send Bug Report"
,(concat "mailto:" "drew.adams" "@" "oracle" ".com?subject=\
buff-menu+.el bug: \
&body=Describe bug here, starting with `emacs -q'. \
Don't forget to mention your Emacs and library versions."))
:link '(url-link :tag "Other Libraries by Drew"
"http://www.emacswiki.org/cgi-bin/wiki/DrewsElispLibraries")
:link '(url-link :tag "Download"
"http://www.emacswiki.org/cgi-bin/wiki/buff-menu+.el")
:link '(url-link :tag "Description"
"http://www.emacswiki.org/cgi-bin/wiki/BufferMenu#BufferMenuPlus")
:link '(emacs-commentary-link :tag "Commentary" "buff-menu+")
:group 'tools :group 'convenience))
(when (> emacs-major-version 21)
(defgroup Buffer-Menu-Plus nil
"Enhancements to the buffer menu."
:link `(url-link :tag "Send Bug Report"
,(concat "mailto:" "drew.adams" "@" "oracle" ".com?subject=\
buff-menu+.el bug: \
&body=Describe bug here, starting with `emacs -q'. \
Don't forget to mention your Emacs and library versions."))
:link '(url-link :tag "Other Libraries by Drew"
"http://www.emacswiki.org/cgi-bin/wiki/DrewsElispLibraries")
:link '(url-link :tag "Download"
"http://www.emacswiki.org/cgi-bin/wiki/buff-menu+.el")
:link '(url-link :tag "Description"
"http://www.emacswiki.org/cgi-bin/wiki/BufferMenu#BufferMenuPlus")
:link '(emacs-commentary-link :tag "Commentary" "buff-menu+")
:group 'Buffer-menu :group 'tools :group 'convenience)
(defvar Buffer-menu-buffer+size-computed-width 0
"Max width of all buffer names, plus 4 for initial `CRM '.")
(define-key Buffer-menu-mode-map "-" 'Buffer-menu-decrease-max-buffer+size)
(defun Buffer-menu-decrease-max-buffer+size ()
"Decrease option `Buffer-menu-buffer+size-width' by one."
(interactive)
(let ((orig Buffer-menu-buffer+size-width))
(condition-case nil
(progn
(setq Buffer-menu-buffer+size-width (1- Buffer-menu-buffer+size-width))
(buffer-menu)
(message "New max width: %s" Buffer-menu-buffer+size-width))
(error (progn (setq Buffer-menu-buffer+size-width orig)
(buffer-menu)
(error "Cannot decrease further"))))))
(define-key Buffer-menu-mode-map "+" 'Buffer-menu-increase-max-buffer+size)
(defun Buffer-menu-increase-max-buffer+size ()
"Increase option `Buffer-menu-buffer+size-width' by one."
(interactive)
(when (> (1+ Buffer-menu-buffer+size-width) 150) (error "Cannot increase further"))
(setq Buffer-menu-buffer+size-width (1+ Buffer-menu-buffer+size-width))
(buffer-menu)
(message "New max width: %s" Buffer-menu-buffer+size-width))
(define-key Buffer-menu-mode-map "\C-\M-t" 'Buffer-menu-toggle-time-format)
(defun Buffer-menu-toggle-time-format ()
"Toggle `Buffer-menu-time-format' and redisplay Buffer Menu."
(interactive)
(buffer-menu-set-default-value 'Buffer-menu-time-format
(if (eq 'short Buffer-menu-time-format) 'long 'short))
(buffer-menu))
(define-key Buffer-menu-mode-map "\M-t" 'Buffer-menu-toggle-time-column)
(defun Buffer-menu-toggle-time-column ()
"Toggle `Buffer-menu-time-flag' and redisplay Buffer Menu."
(interactive)
(buffer-menu-set-default-value 'Buffer-menu-time-flag (not Buffer-menu-time-flag))
(buffer-menu))
(define-key Buffer-menu-mode-map "\M-m" 'Buffer-menu-toggle-mode-column)
(defun Buffer-menu-toggle-mode-column ()
"Toggle `Buffer-menu-mode-flag' and redisplay Buffer Menu."
(interactive)
(buffer-menu-set-default-value 'Buffer-menu-mode-flag (not Buffer-menu-mode-flag))
(buffer-menu))
(define-key Buffer-menu-mode-map "\M-f" 'Buffer-menu-toggle-file-column)
(defun Buffer-menu-toggle-file-column ()
"Toggle `Buffer-menu-file-flag' and redisplay Buffer Menu."
(interactive)
(buffer-menu-set-default-value 'Buffer-menu-file-flag (not Buffer-menu-file-flag))
(buffer-menu))
(defun buffer-menu-set-default-value (symb val)
"Set default value of SYMB to VAL.
Update `buffer-menu-font-lock-keywords' accordingly."
(set-default symb val)
(setq buffer-menu-font-lock-keywords (buffer-menu-font-lock-keywords)))
(defun buffer-menu-font-lock-keywords ()
"Returns the list of font lock keywords for the buffer menu."
(let* ((frame-bufs-p (and (boundp 'frame-bufs-mode) frame-bufs-mode))
(bit-column-header (if frame-bufs-p "CRM[ F].*" "CRM.*"))
(bits (if frame-bufs-p "....." "...."))
(shortbits (if frame-bufs-p "...." "...")))
(list
(list (concat "^\\(" bit-column-header "\\)") 1 'buffer-menu-headings)
(list (concat "^" bits
"\\(.*[^ \t\n]\\)[ \t]+[0-9]+[ \t]+\\(.* \\(AM\\|PM\\)\\)?\\([^/\n]+\\)")
(list 1 'buffer-menu-buffer-name))
(cond (Buffer-menu-mode-flag
(list (concat "^" bits "\\(.*[^ \t\n]\\)[ \t]+[0-9]+[ \t]+[a-zA-Z :0-9]*[ \t]+Dired")
1 'buffer-menu-directory-buffer t t))
(Buffer-menu-file-flag
(list (concat "^" bits "\\(.*[^ \t\n]\\)[ \t]+[0-9]+[ \t]+[^/\n]+[ \t\n]\
\\(\\([~]\\|\\([a-zA-Z]:\\)\\)?/.*/\\)$")
1 'buffer-menu-directory-buffer t t))
(t (list "")))
(list (concat "^" bits
"\\(\\*.*[^ \t\n][[*]\\(<[0-9]+>\\)?\\)[ \t]+")
1 'buffer-menu-star-buffer t t)
(cond ((and Buffer-menu-time-flag Buffer-menu-mode-flag (eq 'short Buffer-menu-time-format))
(list "^.*[ \t][0-9]+[ \t]+\\([0-2][0-9]:[0-5][0-9]:[0-5][0-9]\\)?\\([^\n]+\\)"
(list 1 'buffer-menu-time t t) (list 2 'buffer-menu-mode t t)))
((and Buffer-menu-time-flag Buffer-menu-mode-flag)
(list "^.*[ \t][0-9]+[ \t]+\\(.* \\(AM\\|PM\\)\\)?\\([^\n]+\\)"
(list 1 'buffer-menu-time t t) (list 3 'buffer-menu-mode t t)))
(Buffer-menu-time-flag
(if (eq 'short Buffer-menu-time-format)
(list "^.*[ \t][0-9]+[ \t]+\\([0-2][0-9]:[0-5][0-9]:[0-5][0-9]\\)?"
(list 1 'buffer-menu-time t t))
(list "^.*[ \t][0-9]+[ \t]+\\(.* \\(AM\\|PM\\)\\)?" (list 1 'buffer-menu-time t t))))
(Buffer-menu-mode-flag
(list "^.*[ \t][0-9]+[ \t]+\\([^/\n]+\\)" 1 'buffer-menu-mode t t))
(t ""))
(list "^.*[ \t]\\([0-9]+\\)\\( \\|[\n]\\)" 1 'buffer-menu-size t t)
(if Buffer-menu-file-flag
(list "^.*[ \t][0-9]+[ \t]+[^/\n]+[ \t\n]\
\\(\\(\\([~]\\|\\([a-zA-Z]:\\)\\)*/.*\\)\\|([^ \t]+).*\\)$"
1 'buffer-menu-file-name t t)
"")
(list "^\\([.]\\)" 1 'buffer-menu-current-buffer t t)
(list "^\\(>\\)" 1 'buffer-menu-view-mark t t)
(list (concat "^>" shortbits
"\\(.*[^ \t\n]\\)[ \t]+[0-9]+[ \t]+\\(.* \\(AM\\|PM\\)\\)?\\([^/\n]+\\)")
(list 1 'buffer-menu-marked-buffer 'prepend t))
(list (concat "^D" shortbits
"\\(.*[^ \t\n]\\)[ \t]+[0-9]+[ \t]+\\(.* \\(AM\\|PM\\)\\)?\\([^/\n]+\\)")
(list 1 'buffer-menu-flagged-buffer t t))
(list "^\\(D\\)" 1 'buffer-menu-delete-mark t t)
(list "^..\\(S\\)" 1 'buffer-menu-save-mark t t)
(list "^..\\([*]\\)" 1 'buffer-menu-modified-mark t t)
(list "^.\\(%\\)" 1 'buffer-menu-read-only-mark t t)
)))
(defcustom Buffer-menu-time-format 'short
"*Format for Time column of buffer menu."
:type '(choice
(const :tag "Short: hh:mm:ss" short)
(const :tag "Long: day hh:mm:ss AM/PM" long))
:group 'Buffer-Menu-Plus)
(defcustom Buffer-menu-time-flag t
"*Non-nil means Buffer Menu displays the last time the buffer was displayed."
:type 'boolean :group 'Buffer-Menu-Plus
:initialize 'custom-initialize-default
:set 'buffer-menu-set-default-value)
(defcustom Buffer-menu-mode-flag t
"*Non-nil means Buffer Menu displays the buffer's mode."
:type 'boolean :group 'Buffer-Menu-Plus
:initialize 'custom-initialize-default
:set 'buffer-menu-set-default-value)
(defcustom Buffer-menu-file-flag t
"*Non-nil means Buffer Menu displays the buffer's file."
:type 'boolean :group 'Buffer-Menu-Plus
:initialize 'custom-initialize-default
:set 'buffer-menu-set-default-value)
(defcustom Buffer-menu-sort-column 1
"*Sorted by (1) visit, (2) buffer, (3) size, (4) time, (5) mode, (6) file.
Click a column heading to sort by that field and update this option."
:type '(choice
(const :tag "Sort by time of last visit" 1)
(const :tag "Sort by buffer name" 2)
(const :tag "Sort by buffer size" 3)
(const :tag "Sort by time of last use" 4)
(const :tag "Sort by file name" 5))
:group 'Buffer-Menu-Plus)
(setq Buffer-menu-sort-column (or Buffer-menu-sort-column 1))
(defun Buffer-menu-buffer+size (name size &optional name-props size-props)
(if (> (+ (length name) (length size) 1) Buffer-menu-buffer+size-computed-width)
(setq name (if (string-match "<[0-9]+>$" name)
(concat (substring name 0 (- Buffer-menu-buffer+size-computed-width
(max (length size) 3)
(match-end 0)
(- (match-beginning 0))
2))
"["
(match-string 0 name))
(concat (substring name 0 (- Buffer-menu-buffer+size-computed-width
(max (length size) 3)
2))
"[")))
(setq name (copy-sequence name)))
(when name-props (add-text-properties 0 (length name) name-props name))
(when size-props (add-text-properties 0 (length size) size-props size))
(concat name (make-string (- Buffer-menu-buffer+size-computed-width
(length name)
(length size))
?\ )
size))
)
(unless (and (boundp 'Buffer-menu-buffer+size-width) Buffer-menu-buffer+size-width)
(setq Buffer-menu-buffer+size-width 26))
(defface buffer-menu-headings
'((((background dark))
(:foreground "#00005A5AFFFF" :background "#FFFF9B9BFFFF"))
(t (:foreground "Orange" :background "DarkGreen")))
"*Face used for headings in *Buffer List* buffer."
:group 'Buffer-Menu-Plus
:group 'font-lock-highlighting-faces)
(defvar buffer-menu-headings 'buffer-menu-headings)
(defface buffer-menu-current-buffer
'((((background dark)) (:foreground "Cyan" :background "#808000002B2B"))
(t (:foreground "Red" :background "Aquamarine")))
"*Face used for current buffer mark in *Buffer List* buffer."
:group 'Buffer-Menu-Plus
:group 'font-lock-highlighting-faces)
(defvar buffer-menu-current-buffer 'buffer-menu-current-buffer)
(defface buffer-menu-view-mark
'((((background dark)) (:foreground "Cyan" :background "#808000002B2B"))
(t (:foreground "Red" :background "Aquamarine")))
"*Face used for buffers to view mark (>) in *Buffer List* buffer."
:group 'Buffer-Menu-Plus
:group 'font-lock-highlighting-faces)
(defvar buffer-menu-view-mark 'buffer-menu-view-mark)
(defface buffer-menu-star-buffer
'((((background dark)) (:foreground "#FFFFFFFF7474"))
(t (:foreground "DarkBlue")))
"*Face used for buffers named \"*...*\"in *Buffer List* buffer."
:group 'Buffer-Menu-Plus :group 'font-lock-highlighting-faces)
(defvar buffer-menu-star-buffer 'buffer-menu-star-buffer)
(defface buffer-menu-directory-buffer
'((((background dark)) (:foreground "Yellow" :background "#525227271919"))
(t (:foreground "Blue" :background "LightBlue")))
"*Face used for directory buffers in *Buffer List* buffer."
:group 'Buffer-Menu-Plus :group 'font-lock-highlighting-faces)
(defvar buffer-menu-directory-buffer 'buffer-menu-directory-buffer)
(defface buffer-menu-marked-buffer
'((t (:underline t)))
"*Face used for buffers marked with `>' in *Buffer List* buffer."
:group 'Buffer-Menu-Plus :group 'font-lock-highlighting-faces)
(defvar buffer-menu-marked-buffer 'buffer-menu-marked-buffer)
(defface buffer-menu-flagged-buffer
'((((background dark)) (:foreground "Cyan"))
(t (:foreground "Red")))
"*Face used for buffers marked with `D' in *Buffer List* buffer."
:group 'Buffer-Menu-Plus :group 'font-lock-highlighting-faces)
(defvar buffer-menu-flagged-buffer 'buffer-menu-flagged-buffer)
(defface buffer-menu-delete-mark
'((((background dark)) (:foreground "#808000002B2B" :background "Cyan"))
(t (:foreground "Aquamarine" :background "Red")))
"*Face used for buffers to delete mark (D) in *Buffer List* buffer."
:group 'Buffer-Menu-Plus
:group 'font-lock-highlighting-faces)
(defvar buffer-menu-delete-mark 'buffer-menu-delete-mark)
(defface buffer-menu-save-mark
'((((background dark)) (:foreground "#00005A5AFFFF" :background "Yellow"))
(t (:foreground "Orange" :background "Blue")))
"*Face used for buffers to save mark (S) in *Buffer List* buffer."
:group 'Buffer-Menu-Plus
:group 'font-lock-highlighting-faces)
(defvar buffer-menu-save-mark 'buffer-menu-save-mark)
(defface buffer-menu-modified-mark
'((((background dark)) (:foreground "#00007373FFFF"))
(t (:foreground "DarkOrange")))
"*Face used for modified buffers mark (*) in *Buffer List* buffer."
:group 'Buffer-Menu-Plus
:group 'font-lock-highlighting-faces)
(defvar buffer-menu-modified-mark 'buffer-menu-modified-mark)
(defface buffer-menu-read-only-mark
'((((background dark)) (:foreground "Blue"))
(t (:foreground "Yellow")))
"*Face used for read-only buffers mark (%) in *Buffer List* buffer."
:group 'Buffer-Menu-Plus
:group 'font-lock-highlighting-faces)
(defvar buffer-menu-read-only-mark 'buffer-menu-read-only-mark)
(defface buffer-menu-buffer-name
'((((background dark)) (:foreground "Yellow"))
(t (:foreground "Blue")))
"*Face used for buffer names in *Buffer List* buffer."
:group 'Buffer-Menu-Plus
:group 'font-lock-highlighting-faces)
(defvar buffer-menu-buffer-name 'buffer-menu-buffer-name)
(put 'Buffer-menu-buffer 'face-alias 'buffer-menu-buffer-name)
(defface buffer-menu-mode
'((((background dark)) (:foreground "#FFFF9B9BFFFF"))
(t (:foreground "DarkGreen")))
"*Face used for buffer modes in *Buffer List* buffer."
:group 'Buffer-Menu-Plus
:group 'font-lock-highlighting-faces)
(defvar buffer-menu-mode 'buffer-menu-mode)
(defface buffer-menu-size
'((((background dark)) (:foreground "#7474FFFFFFFF"))
(t (:foreground "DarkRed")))
"*Face used for buffer sizes in *Buffer List* buffer."
:group 'Buffer-Menu-Plus
:group 'font-lock-highlighting-faces)
(defvar buffer-menu-size 'buffer-menu-size)
(defface buffer-menu-time
'((((background dark)) (:foreground "#74749A9AF7F7"))
(t (:foreground "DarkGoldenrod4")))
"*Face used for buffer time in *Buffer List* buffer."
:group 'Buffer-Menu-Plus
:group 'font-lock-highlighting-faces)
(defvar buffer-menu-time 'buffer-menu-time)
(defface buffer-menu-file-name
'((((background dark)) (:foreground "#7474FFFF7474"))
(t (:foreground "DarkMagenta")))
"*Face used for file names in *Buffer List* buffer."
:group 'Buffer-Menu-Plus
:group 'font-lock-highlighting-faces)
(defvar buffer-menu-file-name 'buffer-menu-file-name)
(if (> emacs-major-version 21)
(defvar buffer-menu-font-lock-keywords (buffer-menu-font-lock-keywords)
"*Expressions to highlight in Buffer Menu mode.")
(defvar buffer-menu-font-lock-keywords
(list
(list "^\\( M.*\\)" 1 'buffer-menu-headings)
(list "^....\\(.*[^ \t\n]\\)[ \t]+[0-9]+[ \t]+"
1 'buffer-menu-buffer-name)
(list "^....\\(.*[^ \t\n]\\)[ \t]+[0-9]+[ \t]+[a-zA-Z :0-9]*[ \t]+Dired"
1 'buffer-menu-directory-buffer t t)
(list "^....\\(\\*.*[^ \t\n]\\*\\(<[0-9]+>\\)?\\)[ \t]+"
1 'buffer-menu-star-buffer t t)
(list "^.*[ \t][0-9]+[ \t]+\\([^/\n]+\\)" 1 'buffer-menu-mode t t)
(list "^.*[ \t]\\([0-9]+\\)[ \t]+[^/\n]+" 1 'buffer-menu-size t t)
(list "^.*[ \t][0-9]+[ \t]+[^/\n]+[ \t\n]\\(\\([~]\\|\\([a-zA-Z]:\\)\\)*/.*\\)$"
1 'buffer-menu-file-name t t)
(list "^\\([.]\\)" 1 'buffer-menu-current-buffer t t)
(list "^\\(>\\)" 1 'buffer-menu-view-mark t t)
(list "^>...\\(.*[^ \t\n]\\)[ \t\]+[0-9]"
1 'buffer-menu-marked-buffer 'prepend t)
(list "^D...\\(.*[^ \t\n]\\)[ \t\]+[0-9]"
1 'buffer-menu-flagged-buffer t t)
(list "^\\(D\\)" 1 'buffer-menu-delete-mark t t)
(list "^.\\(S\\)" 1 'buffer-menu-save-mark t t)
(list "^.\\([*]\\)" 1 'buffer-menu-modified-mark t t)
(list "^..\\(%\\)" 1 'buffer-menu-read-only-mark t t)
) "*Expressions to highlight in Buffer Menu mode."))
(when (fboundp 'undefine-killer-commands) (undefine-killer-commands Buffer-menu-mode-map))
(defun Buffer-menu-revert-function (ignore1 ignore2)
(unless (eq buffer-undo-list t) (setq buffer-undo-list ()))
(let ((opoint (point))
(eobp (eobp))
(ocol (current-column))
(oline (progn (move-to-column Buffer-menu-buffer-column)
(get-text-property (point) 'buffer)))
(prop (point-min))
(buffer-undo-list t))
(with-current-buffer (window-buffer)
(list-buffers-noselect (and (boundp 'Buffer-menu-files-only) Buffer-menu-files-only)))
(if oline
(while (setq prop (next-single-property-change prop 'buffer))
(when (eq (get-text-property prop 'buffer) oline)
(goto-char prop)
(move-to-column ocol)))
(goto-char (if eobp (point-max) opoint)))))
(defun Buffer-menu-fontify-and-adjust-frame ()
"Use for `Buffer-menu-mode-hook'. Fontify, fit and raise frame."
(with-current-buffer (get-buffer-create "*Buffer List*")
(when (< emacs-major-version 21) (make-local-variable 'font-lock-defaults))
(setq font-lock-defaults '(buffer-menu-font-lock-keywords t))
(turn-on-font-lock)
(when (get-buffer-window (current-buffer) 'visible)
(save-window-excursion
(select-window (get-buffer-window (current-buffer) 'visible))
(when (and (fboundp 'fit-frame) (one-window-p t)) (fit-frame))
(raise-frame)))
(when (fboundp 'font-lock-refresh-defaults) (font-lock-refresh-defaults))))
(if (> emacs-major-version 22)
(add-hook 'Buffer-menu-mode-hook 'Buffer-menu-fontify-and-adjust-frame)
(add-hook 'buffer-menu-mode-hook 'Buffer-menu-fontify-and-adjust-frame))
(defun Buffer-menu-beginning ()
(goto-char (point-min))
(unless (and (boundp 'Buffer-menu-use-header-line) Buffer-menu-use-header-line)
(forward-line)))
(defun buffer-menu (&optional arg)
"Show a menu to let you save, delete or select buffers.
By default (no or null prefix arg), the buffers are listed in order of
last access (visit). With a non-nil prefix ARG:
ARG >= 0 means only buffers visiting files are listed.
ARG <= 0 means the buffers are listed alphabetically.
(ARG = 0 means only buffers visiting files, listed alphabetically.)
Type `?' in buffer \"*Buffer List*\" for more information.
Type `q' there to quit the buffer menu."
(interactive "P")
(let ((num-arg (prefix-numeric-value arg)))
(if (and arg (< num-arg 0)) (list-buffers) (list-buffers arg))
(let ((newpoint (save-excursion (set-buffer "*Buffer List*") (point))))
(pop-to-buffer "*Buffer List*")
(when (and arg (not (> num-arg 0)))
(let ((buffer-read-only nil))
(goto-char (point-min))
(unless Buffer-menu-use-header-line (forward-line 2))
(forward-char Buffer-menu-buffer-column)
(sort-columns nil (point) (save-excursion (goto-char (point-max))
(when (bolp) (backward-char 1))
(point)))))
(goto-char newpoint)))
(message "Help: ?; Menu: mouse-3; Show: v; Mark: u,m,s,d; \
Save/Delete: x; Misc: g,~,%%,t"))
(when (< emacs-major-version 23)
(defun Buffer-menu-mode ()
"Major mode for editing a list of buffers.
Each line describes one of the buffers in Emacs.
In Buffer menu mode, chars do not insert themselves, but are commands.
\\<Buffer-menu-mode-map>
\(\"Current line\" here is the line of the text cursor or the mouse.)
Display Options
---------------
Click `mouse-3' for a context-sensitive menu of buffer operations.
These features are available for Emacs 22 and later:
* You can click a column heading to sort by that column. Clicking
again reverses the sort direction. The current sort column is
indicated by an underlined or overlined column heading. Sorting by
column `CRM' depends on the value of option
`Buffer-menu-use-frame-buffer-list'.
* You can resize the Buffer and Size columns using `+' and `-'.
* You can toggle showing columns Time, Mode, and File using
`\\[Buffer-menu-toggle-time-column]',
`\\[Buffer-menu-toggle-mode-column]', and
`\\[Buffer-menu-toggle-file-column]'.
You can toggle the Time format using
`\\[Buffer-menu-toggle-time-format]]'.
(These re only for Emacs 21 and later.)
Column `CRM':
`C' shows `>' if you have marked the buffer to be displayed,
`D' if you have marked it for deletion, and
`.' for the buffer from which you came (current).
`R' shows `%' if the buffer is read-only.
`M' shows `*' if the buffer is modified, and
`S' if you have marked it for saving.
The other columns are the Buffer name, its Size in characters, the
last Time the buffer was displayed, its major Mode, and the visited
File name (if any).
Displaying Buffers
------------------
\\[Buffer-menu-mouse-select], \\[Buffer-menu-select], \\[Buffer-menu-this-window] -- \
Select current line's buffer.
\\[Buffer-menu-mark]\t-- Mark current line's buffer `>' to be displayed (via \
`\\[Buffer-menu-select]').
\\[Buffer-menu-select]\t-- Show buffers marked `>'. Select current line's \
buffer.
\\[Buffer-menu-1-window]\t-- Select current line's buffer (only) in a \
full-frame window.
\\[Buffer-menu-2-window]\t-- Select current line's buffer in one window.
\t Display previous buffer in a second window.
\\[Buffer-menu-switch-other-window]\t-- Display current line's buffer in \
another window. No select.
\\[Buffer-menu-view]\t-- select current line's buffer, but in view-mode.
\\[Buffer-menu-view-other-window]\t-- select that buffer in
another window, in view-mode.
\\[Buffer-menu-toggle-files-only]\t-- toggle whether to display only file buffers.
Marking/Unmarking Buffers to be Saved/Deleted
---------------------------------------------
\\[Buffer-menu-save]\t-- Mark current line's buffer `S' to be saved. \
Cursor down.
\\[Buffer-menu-delete]\t-- Mark current line's buffer `D' to be deleted. \
Cursor down.
\\[Buffer-menu-delete-backwards]\t-- Mark current line's buffer `D' to be \
deleted. Cursor up.
\\[Buffer-menu-unmark]\t-- Unmark current line. Cursor down. (Prefix arg: \
Cursor up.)
\\[Buffer-menu-backup-unmark]\t-- Cursor up, then unmark line.
Saving/Deleting Buffers
-----------------------
\\[Buffer-menu-execute]\t-- Save / Delete marked buffers (marks `S', `D').
\\[Buffer-menu-delete-flagged]\t-- Delete all buffers marked `D', even if modified.
Miscellaneous
-------------
\\[Buffer-menu-revert]\t-- Update the list of buffers.
\\[Buffer-menu-not-modified]\t-- Clear modified-flag on current line's buffer.
\\[Buffer-menu-toggle-read-only]\t-- Toggle read-only status of current \
line's buffer.
\\[Buffer-menu-visit-tags-table]\t-- `visit-tags-table' using current line's \
buffer.
Bindings in Buffer Menu mode:
----------------------------
\\{Buffer-menu-mode-map}"
(kill-all-local-variables)
(use-local-map Buffer-menu-mode-map)
(setq major-mode 'Buffer-menu-mode
mode-name "Buffer Menu")
(save-excursion
(goto-char (point-min))
(when (< emacs-major-version 20)
(search-forward "Buffer")
(backward-word 1)
(setq Buffer-menu-buffer-column (current-column)))
(when (or (not (boundp 'Buffer-menu-use-header-line)) (not Buffer-menu-use-header-line))
(forward-line 2))
(while (not (eobp))
(put-text-property (point) (line-end-position) 'mouse-face 'highlight)
(forward-line 1)))
(set (make-local-variable 'revert-buffer-function) 'Buffer-menu-revert-function)
(when (> emacs-major-version 21)
(set (make-local-variable 'buffer-stale-function) #'(lambda (&optional noconfirm) 'fast)))
(setq truncate-lines t
buffer-read-only t)
(if (> emacs-major-version 21)
(if (> emacs-major-version 22)
(run-mode-hooks 'Buffer-menu-mode-hook)
(run-mode-hooks 'buffer-menu-mode-hook))
(run-hooks 'buffer-menu-mode-hook))))
(when (> emacs-major-version 22)
(put 'Buffer-menu-mode 'mode-class 'special)
(define-derived-mode Buffer-menu-mode special-mode "Buffer Menu"
"Major mode for editing a list of buffers.
Each line describes one of the buffers in Emacs.
In Buffer menu mode, chars do not insert themselves, but are commands.
\\<Buffer-menu-mode-map>
\(\"Current line\" here is the line of the text cursor or the mouse.)
Display Options
---------------
Click `mouse-3' for a context-sensitive menu of buffer operations.
These features are available for Emacs 22 and later:
* You can click a column heading to sort by that column. Clicking
again reverses the sort direction. The current sort column is
indicated by an underlined or overlined column heading. Sorting by
column `CRM' depends on the value of option
`Buffer-menu-use-frame-buffer-list'.
* You can resize the Buffer and Size columns using `+' and `-'.
* You can toggle showing columns Time, Mode, and File using `\\[Buffer-menu-toggle-time-column]',
`\\[Buffer-menu-toggle-mode-column]', and `\\[Buffer-menu-toggle-file-column]'. You can toggle \
the Time format using `\\[Buffer-menu-toggle-time-format]'.
Column `CRM':
`C' shows `>' if you have marked the buffer to be displayed,
`D' if you have marked it for deletion, and
`.' for the buffer from which you came (current).
`R' shows `%' if the buffer is read-only.
`M' shows `*' if the buffer is modified, and
`S' if you have marked it for saving.
The other columns are the Buffer name, its Size in characters, the
last Time the buffer was displayed, its major Mode, and the visited
File name (if any).
Displaying Buffers
------------------
\\[Buffer-menu-mouse-select], \\[Buffer-menu-select], \\[Buffer-menu-this-window], \
\\[Buffer-menu-other-window] -- Select current line's buffer.
\\[Buffer-menu-mark]\t-- Mark current line's buffer `>' to be displayed (via \
`\\[Buffer-menu-select]').
\\[Buffer-menu-select]\t-- Show buffers marked `>'. Select current line's \
buffer.
\\[Buffer-menu-1-window]\t-- Select current line's buffer (only) in a \
full-frame window.
\\[Buffer-menu-2-window]\t-- Select current line's buffer in one window.
\t Display previous buffer in a second window.
\\[Buffer-menu-switch-other-window]\t-- Display current line's buffer in \
another window. No select.
\\[Buffer-menu-view]\t-- select current line's buffer, but in view-mode.
\\[Buffer-menu-view-other-window]\t-- select that buffer in
another window, in view-mode.
\\[Buffer-menu-toggle-files-only]\t-- toggle whether to display only file & Dired buffers.
Marking/Unmarking Buffers to be Saved/Deleted
---------------------------------------------
\\[Buffer-menu-save]\t-- Mark current line's buffer `S' to be saved. \
Cursor down.
\\[Buffer-menu-delete]\t-- Mark current line's buffer `D' to be deleted. \
Cursor down.
\\[Buffer-menu-delete-backwards]\t-- Mark current line's buffer `D' to be \
deleted. Cursor up.
\\[Buffer-menu-unmark]\t-- Unmark current line. Cursor down. (Prefix arg: \
Cursor up.)
\\[Buffer-menu-backup-unmark]\t-- Cursor up, then unmark line.
Saving/Deleting Buffers
-----------------------
\\[Buffer-menu-execute]\t-- Save / Delete marked buffers (marks `S', `D').
\\[Buffer-menu-delete-flagged]\t-- Delete all buffers marked `D', even if modified.
Miscellaneous
-------------
\\[revert-buffer]\t-- Update the list of buffers.
\\[Buffer-menu-not-modified]\t-- Clear modified-flag on current line's buffer.
\\[Buffer-menu-toggle-read-only]\t-- Toggle read-only status of current \
line's buffer.
\\[Buffer-menu-visit-tags-table]\t-- `visit-tags-table' using current line's \
buffer.
\\[Buffer-menu-isearch-buffers] -- Do incremental search in the marked buffers.
\\[Buffer-menu-isearch-buffers-regexp] -- Isearch for regexp in the marked buffers.
\\[Buffer-menu-bury] -- bury the buffer listed on this line.
Bindings in Buffer Menu mode:
----------------------------
\\{Buffer-menu-mode-map}"
(save-excursion
(let ((inhibit-read-only t))
(goto-char (point-min))
(when (or (not (boundp 'Buffer-menu-use-header-line)) (not Buffer-menu-use-header-line))
(forward-line 2))
(while (not (eobp))
(put-text-property (point) (line-end-position) 'mouse-face 'highlight)
(forward-line 1))))
(set (make-local-variable 'revert-buffer-function) 'Buffer-menu-revert-function)
(set (make-local-variable 'buffer-stale-function) #'(lambda (&optional noconfirm) 'fast))
(setq truncate-lines t
buffer-read-only t)))
(define-key Buffer-menu-mode-map "\C-\M-x" 'Buffer-menu-delete-flagged)
(defun Buffer-menu-delete-flagged ()
"Delete all buffers marked `D', even if they have been modified.
If there are any file buffers that have been modified since the last
save, then you must confirm the deletion of all at once.
You can mark a buffer for deletion (`D') using command `\\<Buffer-menu-mode-map>\
\\[Buffer-menu-delete]'."
(interactive)
(save-excursion
(Buffer-menu-beginning)
(let ((buff-menu-buffer (current-buffer))
(buffer-read-only nil)
(bufs ())
(mod-bufs ())
(kill-fn (if (fboundp 'kill-buffer-and-its-windows)
#'kill-buffer-and-its-windows
#'kill-buffer))
buf)
(while (re-search-forward "^D" nil t)
(forward-char -1)
(setq buf (Buffer-menu-buffer nil))
(unless (or (eq buf nil) (eq buf buff-menu-buffer))
(push buf bufs)
(when (and (buffer-file-name buf) (buffer-modified-p buf)) (push buf mod-bufs)))
(forward-line 1))
(unless bufs (error "No buffers flagged for deletion"))
(when (and mod-bufs (let ((visible-bell t)) (ding) t)
(let ((last-nonmenu-event nil)
(use-dialog-box t))
(not (yes-or-no-p
(concat "Modified buffers. Delete all anyway? (`"
(mapconcat (lambda (b) (buffer-name b)) mod-bufs "', `")
"')")))))
(error "OK, no buffers deleted"))
(dolist (buf bufs)
(save-excursion
(set-buffer buf)
(set-buffer-modified-p nil)
(funcall kill-fn buf)))
(Buffer-menu-revert-function nil nil))))
(defun Buffer-menu-execute ()
"Save or delete buffers marked `S' (\"save\") or `D' (\"delete\").
Buffers can be so marked using commands `\\<Buffer-menu-mode-map>\
\\[Buffer-menu-save]' and `\\[Buffer-menu-delete]', respectively."
(interactive)
(when (and (boundp 'frame-bufs-mode) frame-bufs-mode) (frame-bufs-buffer-menu-execute))
(save-excursion
(Buffer-menu-beginning)
(while (if (> emacs-major-version 21)
(re-search-forward "^..S" nil t)
(re-search-forward "^.S" nil t))
(let ((modp nil))
(save-excursion
(set-buffer (Buffer-menu-buffer t))
(save-buffer)
(setq modp (buffer-modified-p)))
(let ((buffer-read-only nil))
(delete-char -1)
(insert (if modp ?* ? ))))))
(save-excursion
(Buffer-menu-beginning)
(let ((buff-menu-buffer (current-buffer))
(buffer-read-only nil))
(while (re-search-forward "^D" nil t)
(forward-char -1)
(let ((buf (Buffer-menu-buffer nil)))
(or (eq buf nil) (eq buf buff-menu-buffer)
(save-excursion (if (fboundp 'kill-buffer-and-its-windows)
(kill-buffer-and-its-windows buf)
(kill-buffer buf))))
(if (and buf (buffer-name buf))
(progn (delete-char 1) (insert ? ))
(delete-region (point) (progn (forward-line 1) (point)))
(unless (bobp) (forward-char -1))))))))
(when (or (> emacs-major-version 24)
(and (= emacs-major-version 24) (> emacs-minor-version 2)))
(defun Buffer-menu-select ()
"Select this line's buffer; also display buffers marked with `>'.
You can mark buffers with command `\\<Buffer-menu-mode-map>\\[Buffer-menu-mark]'.
Delete and replace any previously existing windows in the selected
frame. But if the Buffer Menu window is dedicated, do not delete it."
(interactive)
(let* ((line-buffer (Buffer-menu-buffer t))
(menu-buffer (current-buffer))
(others (delq line-buffer (Buffer-menu-marked-buffers t))))
(cond ((window-dedicated-p (selected-window))
(pop-to-buffer line-buffer)
(unless (eq menu-buffer line-buffer) (bury-buffer menu-buffer))
(dolist (buf others) (pop-to-buffer buf)))
(t
(delete-other-windows)
(switch-to-buffer line-buffer)
(unless (eq menu-buffer line-buffer) (bury-buffer menu-buffer))
(let ((height (/ (1- (frame-height)) (1+ (length others)))))
(dolist (buf others)
(split-window nil height)
(other-window 1)
(switch-to-buffer buf)))
(other-window 1))))))
(unless (or (> emacs-major-version 24)
(and (= emacs-major-version 24) (> emacs-minor-version 2)))
(defun Buffer-menu-select ()
"Select this line's buffer; also display buffers marked with `>'.
You can mark buffers with command `\\<Buffer-menu-mode-map>\\[Buffer-menu-mark]'.
Delete and replace any previously existing windows in the selected
frame. But if the Buffer Menu window is dedicated, do not delete it."
(interactive)
(let ((buff (Buffer-menu-buffer t))
(menu (current-buffer))
(others ())
tem)
(Buffer-menu-beginning)
(while (re-search-forward "^>" nil t)
(setq tem (Buffer-menu-buffer t))
(let ((buffer-read-only nil)) (delete-char -1) (insert ?\ ))
(or (eq tem buff) (memq tem others) (setq others (cons tem others))))
(setq others (nreverse others))
(cond ((window-dedicated-p (selected-window))
(pop-to-buffer buff)
(unless (eq menu buff) (bury-buffer menu))
(while others
(pop-to-buffer (car others))
(pop others)))
(t
(setq tem (/ (1- (frame-height)) (1+ (length others))))
(delete-other-windows)
(switch-to-buffer buff)
(unless (eq menu buff) (bury-buffer menu))
(if (equal (length others) 0)
(progn
(switch-to-buffer buff))
(while others
(split-window nil tem)
(other-window 1)
(switch-to-buffer (car others))
(setq others (cdr others)))
(other-window 1)))))))
(when (> emacs-major-version 21)
(defun Buffer-menu-sort (column)
"Sort the buffer menu by COLUMN.
Consecutive executions of the same COLUMN reverse the sort order."
(interactive "P")
(when column
(setq column (prefix-numeric-value column))
(when (= column 0) (setq column 1))
(when (> column 6) (setq column 6))
(when (< column -6) (setq column -6)))
(if (equal Buffer-menu-sort-column column)
(setq Buffer-menu-sort-column (- column))
(setq Buffer-menu-sort-column column))
(let (buffer-read-only lll buf m1 m2)
(save-excursion
(Buffer-menu-beginning)
(while (not (eobp))
(when (buffer-live-p
(setq buf (get-text-property (+ (point) Buffer-menu-buffer-column) 'buffer)))
(setq m1 (char-after)
m1 (and (memq m1 '(?> ?D)) m1)
m2 (char-after (+ (point) 2))
m2 (and (eq m2 ?S) m2))
(when (or m1 m2) (push (list buf m1 m2) lll)))
(forward-line)))
(Buffer-menu-revert-function nil nil)
(setq buffer-read-only t)
(save-excursion
(Buffer-menu-beginning)
(while (not (eobp))
(when (setq buf (assq (get-text-property (+ (point) Buffer-menu-buffer-column) 'buffer)
lll))
(setq m1 (cadr buf)
m2 (cadr (cdr buf)))
(when m1 (delete-char 1) (insert m1) (backward-char 1))
(when m2 (forward-char 2) (delete-char 1) (insert m2)))
(forward-line))))
(message "Buffers are now sorted %s%s."
(case (abs column)
(1 "by time of last visit - see `Buffer-menu-use-frame-buffer-list'")
(2 "by buffer name")
(3 "by size")
(4 "by time of last display")
(5 "by major-mode name")
(otherwise "by associated file (including path)"))
(if (natnump Buffer-menu-sort-column) ", ascending" ", descending"))))
(when (> emacs-major-version 21)
(defun Buffer-menu-make-sort-button (name button-column)
(let ((the-sort-column-p nil))
(when (equal button-column (abs Buffer-menu-sort-column))
(setq the-sort-column-p t
button-column (- button-column)))
(propertize name 'column button-column
'help-echo (case (abs button-column)
(1 (if Buffer-menu-use-header-line
"mouse-1, mouse-2: sort by time of last visit - \
see `Buffer-menu-use-frame-buffer-list'"
"mouse-2, RET: sort by time of last visit - \
see `Buffer-menu-use-frame-buffer-list'"))
(2 (if Buffer-menu-use-header-line
"mouse-1, mouse-2: sort by buffer name"
"mouse-2, RET: sort by buffer name"))
(4 "mouse-1, mouse-2: sort by time of last display/access")
(t (if Buffer-menu-use-header-line
(concat "mouse-1, mouse-2: sort by " (downcase name))
(concat "mouse-2, RET: sort by " (downcase name)))))
'mouse-face 'highlight
(when the-sort-column-p 'face) (when the-sort-column-p
(if (natnump Buffer-menu-sort-column)
'(:underline t)
'(:overline t)))
'keymap Buffer-menu-sort-button-map))))
(when (> emacs-major-version 21)
(defun list-buffers-noselect (&optional files-only buffer-list)
"Create and return a buffer with a list of names of existing buffers.
The buffer is named `*Buffer List*'.
Note that buffers with names starting with spaces are omitted.
Non-null optional arg FILES-ONLY means mention only file buffers.
If BUFFER-LIST is non-nil, it should be a list of buffers;
it means list those buffers and no others.
For more information, see the function `buffer-menu'."
(let ((len 0)
buf+size)
(unless Buffer-menu-buffer+size-width (setq Buffer-menu-buffer+size-width 26))
(setq Buffer-menu-buffer+size-computed-width Buffer-menu-buffer+size-width)
(dolist (buffer (buffer-list))
(setq buf+size (concat (buffer-name buffer) (number-to-string (buffer-size buffer))))
(when (and (not (string= (substring buf+size 0 1) " "))
(> (length buf+size) len))
(setq len (length buf+size))))
(when (< (+ len 1) Buffer-menu-buffer+size-width)
(setq Buffer-menu-buffer+size-computed-width (+ len 1))))
(let* ((old-buffer (current-buffer))
(standard-output standard-output)
(mode-end (if Buffer-menu-mode-flag
(make-string (- Buffer-menu-mode-width 4) ?\ )
""))
(frame-bufs-p (and (boundp 'frame-bufs-mode) frame-bufs-mode))
(header
(concat (Buffer-menu-make-sort-button
(concat "CRM" (if frame-bufs-p (if frame-bufs-full-list "F" " ") "")) 1)
" "
(Buffer-menu-buffer+size (Buffer-menu-make-sort-button "Buffer" 2)
(Buffer-menu-make-sort-button "Size" 3))
" "
(and Buffer-menu-time-flag
(if (eq 'short Buffer-menu-time-format)
(Buffer-menu-make-sort-button "Time " 4)
(Buffer-menu-make-sort-button "Time " 4)))
(and Buffer-menu-time-flag " ")
(and Buffer-menu-mode-flag
(Buffer-menu-make-sort-button (concat "Mode" mode-end) 5))
(if Buffer-menu-mode-flag
(if Buffer-menu-time-flag " " " ")
(and (not Buffer-menu-time-flag) " "))
(and Buffer-menu-file-flag (Buffer-menu-make-sort-button
"File " 6))
"\n"))
list desired-point name buffer-time mode file)
(when (and (boundp 'Buffer-menu-use-header-line) Buffer-menu-use-header-line)
(let ((pos 0))
(while (string-match "[ \t\n]+" header pos)
(setq pos (match-end 0))
(put-text-property (match-beginning 0) pos 'display
(list 'space :align-to pos)
header)
(put-text-property (match-beginning 0) (1- pos) 'mouse-face 'highlight header)))
(setq header (concat (propertize " " 'display '(space :align-to 0)) header)))
(with-current-buffer (get-buffer-create "*Buffer List*")
(setq buffer-read-only nil)
(erase-buffer)
(setq standard-output (current-buffer))
(unless (and (boundp 'Buffer-menu-use-header-line) Buffer-menu-use-header-line)
(let ((underline (eval-when-compile (if (> emacs-major-version 21) ?\u2014 ?-))))
(insert header (apply 'string
(mapcar (lambda (ch) (if (memq ch '(?\n ?\ )) ch underline))
header)))))
(dolist (buffer (or buffer-list
(and frame-bufs-p (frame-bufs-buffer-list (selected-frame)
frame-bufs-full-list))
(buffer-list (and Buffer-menu-use-frame-buffer-list
(selected-frame)))))
(with-current-buffer buffer
(let ((name (buffer-name))
(file (or buffer-file-name
(and (eq major-mode 'dired-mode) default-directory))))
(unless (and (not buffer-list)
(or
(and (string= (substring name 0 1) " ") (null file))
(and files-only (not file))
(string= name "*Buffer List*")))
(let (
(buffer-time (and Buffer-menu-time-flag
(cons (or (float-time buffer-display-time) 0)
(if buffer-display-time
(format-time-string
(if (eq 'short Buffer-menu-time-format)
"%02H:%02M:%02S"
"%_3a %_2l:%02M:%02S %_2p")
buffer-display-time)
(if (eq 'short Buffer-menu-time-format)
" "
" ")))))
(mode (concat (format-mode-line mode-name nil nil buffer)
(and mode-line-process
(format-mode-line
mode-line-process nil nil buffer))))
(bits (concat (if (eq buffer old-buffer) "." " ")
(if (or (eq buffer standard-output) buffer-read-only)
"%"
" ")
(if (buffer-modified-p) "*" " ")
(if frame-bufs-p
(frame-bufs-bit-info buffer)
"")
" ")))
(unless file
(cond ((and (boundp 'list-buffers-directory) list-buffers-directory)
(setq file list-buffers-directory))
((eq major-mode 'Info-mode)
(setq file Info-current-file)
(cond ((equal file "dir")
(setq file "*Info Directory*"))
((eq file 'apropos)
(setq file "*Info Apropos*"))
((eq file 'history)
(setq file "*Info History*"))
((eq file 'toc)
(setq file "*Info TOC*"))
((not (stringp file))
(setq file nil))
(t
(setq file (concat "(" (file-name-nondirectory file) ")"
Info-current-node)))))))
(push (list buffer bits name (buffer-size) buffer-time mode file) list))))))
(unless (eq -1 Buffer-menu-sort-column) (setq list (nreverse list)))
(dolist (buffer (if (eq 1 (abs Buffer-menu-sort-column))
list
(let* ((descending-p (natnump Buffer-menu-sort-column))
(Buffer-menu-sort-column (abs Buffer-menu-sort-column)))
(sort list
(cond ((eq Buffer-menu-sort-column 3)
(if descending-p
(lambda (a b) (< (nth 3 a) (nth 3 b)))
(lambda (a b) (< (nth 3 b) (nth 3 a)))))
((eq Buffer-menu-sort-column 4)
(if descending-p
(lambda (a b) (< (car (nth 4 a)) (car (nth 4 b))))
(lambda (a b) (< (car (nth 4 b)) (car (nth 4 a))))))
(t
(if descending-p
(lambda (a b)
(string< (nth Buffer-menu-sort-column a)
(nth Buffer-menu-sort-column b)))
(lambda (a b)
(string< (nth Buffer-menu-sort-column b)
(nth Buffer-menu-sort-column a))))))))))
(when (eq (car buffer) old-buffer) (setq desired-point (point)))
(insert (cadr buffer)
(Buffer-menu-buffer+size (nth 2 buffer)
(int-to-string (nth 3 buffer))
`(buffer-name ,(nth 2 buffer) buffer ,(car buffer)
font-lock-face
,(if (facep 'Buffer-menu-buffer-face)
'Buffer-menu-buffer-face
'Buffer-menu-buffer)
mouse-face highlight
help-echo "mouse-2: select this buffer")))
(when Buffer-menu-time-flag (insert " " (cdr (nth 4 buffer))))
(when Buffer-menu-mode-flag
(insert " "
(if (> (length (nth 5 buffer)) Buffer-menu-mode-width)
(substring (nth 5 buffer) 0 Buffer-menu-mode-width)
(nth 5 buffer))))
(when (and Buffer-menu-file-flag (nth 6 buffer))
(indent-to (+ Buffer-menu-buffer-column Buffer-menu-buffer+size-computed-width
(if Buffer-menu-mode-flag (1+ Buffer-menu-mode-width) 0)
(if Buffer-menu-time-flag
(if (eq 'short Buffer-menu-time-format) 9 16)
0)
3)
1)
(princ (abbreviate-file-name (nth 6 buffer))))
(princ "\n"))
(Buffer-menu-mode)
(when (and (boundp 'Buffer-menu-use-header-line) Buffer-menu-use-header-line)
(setq header-line-format header))
(goto-char (or desired-point (point-min)))
(setq Buffer-menu-files-only files-only)
(set-buffer-modified-p nil)
(current-buffer)))))
(define-key Buffer-menu-mode-map [down-mouse-3] 'Buffer-menu-mouse-3-menu)
(define-key Buffer-menu-mode-map [mouse-3] 'ignore)
(defvar Buffer-menu-overlay nil
"Overlay to highlight line of buffer during popup of `mouse-3' menu.")
(defun Buffer-menu-mouse-3-menu (event)
"Pop up menu for Mouse-3 for buffer listed in buffer menu."
(interactive "e")
(let* ((mouse-pos (event-start event))
bol eol temp
(buffer-name (save-excursion
(set-buffer (window-buffer (posn-window mouse-pos)))
(save-excursion
(goto-char (posn-point mouse-pos))
(setq bol (line-beginning-position)
eol (line-end-position))
(if Buffer-menu-overlay
(move-overlay Buffer-menu-overlay bol eol (current-buffer))
(setq Buffer-menu-overlay (make-overlay bol eol))
(overlay-put Buffer-menu-overlay 'face 'region))
(setq temp (and (not (eobp)) (Buffer-menu-buffer nil)))
(and temp (buffer-name temp))))))
(sit-for 0)
(let ((selection
(x-popup-menu
event
(list
"Menu"
(if buffer-name
(list
buffer-name
'("Select Buffer" . Buffer-menu-mouse-select)
'("Unmark Buffer" . Buffer-menu-mouse-unmark)
'("Mark to Save Buffer (S)" . Buffer-menu-mouse-save)
'("Mark to Delete Buffer (D)" . Buffer-menu-mouse-delete)
'("Mark as Modified/Unmodified (*)" . Buffer-menu-mouse-modified)
'("--")
'("Execute: Save/Delete Marked Buffers" . Buffer-menu-mouse-execute)
'("Delete All `D', Even If Modified" . Buffer-menu-delete-flagged))
(list ""
'("Execute: Save/Delete Marked Buffers" . Buffer-menu-mouse-execute)
'("Delete All `D', Even If Modified" . Buffer-menu-delete-flagged)))))))
(when Buffer-menu-overlay (delete-overlay Buffer-menu-overlay))
(and selection (call-interactively selection)))))
(defun Buffer-menu-mouse-other-window (event)
"Select, in another window, the buffer on whose line you click."
(interactive "e")
(let (buffer)
(save-excursion
(set-buffer (window-buffer (posn-window (event-end event))))
(save-excursion
(goto-char (posn-point (event-end event)))
(setq buffer (Buffer-menu-buffer t))))
(select-window (posn-window (event-end event)))
(switch-to-buffer-other-window buffer)))
(defun Buffer-menu-mouse-unmark (event)
"Cancel all requested operations on buffer."
(interactive "e")
(let ((frame-bufs-p (and (boundp 'frame-bufs) frame-bufs-mode))
buffer)
(save-excursion
(set-buffer (window-buffer (posn-window (event-end event))))
(save-excursion
(goto-char (posn-point (event-end event)))
(setq buffer (Buffer-menu-buffer t))))
(select-window (posn-window (event-end event)))
(goto-char (posn-point (event-end event)))
(beginning-of-line)
(if (looking-at " [-M]")
(ding)
(let* ((mod (buffer-modified-p buffer))
(readonly (save-excursion (set-buffer buffer) buffer-read-only))
(buffer-read-only nil)
(local-info (if frame-bufs-p
(frame-bufs-bit-info buffer)
"")))
(delete-char (if frame-bufs-p 4 3))
(insert (concat (if readonly (if mod " *%" " %") (if mod " * " " ")) local-info))))
(beginning-of-line)))
(defun Buffer-menu-mouse-save (event)
"Mark buffer to be saved.
Actual deletion is done via `\\<Buffer-menu-mode-map>\\[Buffer-menu-execute]' \
or `\\<Buffer-menu-mode-map>\\[Buffer-menu-mouse-execute]'."
(interactive "e")
(select-window (posn-window (event-end event)))
(goto-char (posn-point (event-end event)))
(beginning-of-line)
(forward-char 1)
(if (looking-at " [-M]")
(ding)
(let ((buffer-read-only nil)) (delete-char 1) (insert ?S)))
(beginning-of-line))
(defun Buffer-menu-mouse-delete (event)
"Mark buffer to be deleted.
Actual deletion is done via `\\<Buffer-menu-mode-map>\\[Buffer-menu-execute]' \
or `\\<Buffer-menu-mode-map>\\[Buffer-menu-mouse-execute]'."
(interactive "e")
(select-window (posn-window (event-end event)))
(goto-char (posn-point (event-end event)))
(beginning-of-line)
(if (looking-at " [-M]")
(ding)
(let ((buffer-read-only nil)) (delete-char 1) (insert ?D)))
(beginning-of-line))
(defun Buffer-menu-mouse-modified (event)
"Mark buffer as unmodified (no changes to save) if modified, and vice versa."
(interactive "e")
(select-window (posn-window (event-end event)))
(goto-char (posn-point (event-end event)))
(beginning-of-line)
(forward-char 1)
(let ((buffer-read-only nil)
modified-p)
(save-excursion
(set-buffer (Buffer-menu-buffer t))
(set-buffer-modified-p (not (buffer-modified-p))))
(cond ((= ?\* (char-after (point)))
(delete-char 1)
(insert ?\ ))
(t
(delete-char 1)
(insert ?\*))))
(beginning-of-line))
(defun Buffer-menu-mouse-execute (event)
"Save and/or delete buffers marked `S' or `D', respectively.
Buffers can be marked via commands `\\<Buffer-menu-mode-map>\
\\[Buffer-menu-save]' and `\\<Buffer-menu-mode-map>\\[Buffer-menu-delete]'
\(or `\\<Buffer-menu-mode-map>\\[Buffer-menu-mouse-save]' and \
`\\<Buffer-menu-mode-map>\\[Buffer-menu-mouse-delete]')."
(interactive "e")
(select-window (posn-window (event-end event)))
(when (and (boundp 'frame-bufs-mode) frame-bufs-mode) (frame-bufs-buffer-menu-execute))
(save-excursion
(Buffer-menu-beginning)
(while (if (> emacs-major-version 21)
(re-search-forward "^..S" nil t)
(re-search-forward "^.S" nil t))
(let ((modp nil))
(save-excursion
(set-buffer (Buffer-menu-buffer t))
(save-buffer)
(setq modp (buffer-modified-p)))
(let ((buffer-read-only nil)) (delete-char -1) (insert (if modp ?* ? ))))))
(save-excursion
(Buffer-menu-beginning)
(let ((buff-menu-buffer (current-buffer))
(buffer-read-only nil))
(while (re-search-forward "^D" nil t)
(forward-char -1)
(let ((buf (Buffer-menu-buffer nil)))
(or (eq buf nil) (eq buf buff-menu-buffer)
(save-excursion (if (fboundp 'kill-buffer-and-its-windows)
(kill-buffer-and-its-windows buf)
(kill-buffer buf))))
(if (and buf (buffer-name buf))
(progn (delete-char 1) (insert ? ))
(delete-region (point) (progn (forward-line 1) (point)))
(unless (bobp) (forward-char -1))))))))
(when (> emacs-major-version 21)
(defun buffer-menu-nb-marked-in-mode-name ()
"Add number of marked and flagged lines to mode name in the mode line.
\(Flagged means flagged for deletion.)
If the current line is marked/flagged and there are others
marked/flagged after it then show `N/M', where N is the number
marked/flagged through the current line and M is the total number
marked/flagged."
(setq mode-name
`(,mode-name
(:eval (let* ((marked-regexp "^>")
(nb-marked (count-matches marked-regexp
(point-min) (point-max))))
(if (not (> nb-marked 0))
""
(propertize
(format " %s%d>"
(save-excursion
(forward-line 0)
(if (looking-at (concat marked-regexp ".*"))
(format "%d/" (1+ (count-matches marked-regexp
(point-min) (point))))
""))
nb-marked)
'face 'buffer-menu-mode-line-marked))))
(:eval (let* ((flagged-regexp "^D")
(nb-flagged (count-matches flagged-regexp
(point-min) (point-max))))
(if (not (> nb-flagged 0))
""
(propertize
(format " %s%dD"
(save-excursion
(forward-line 0)
(if (looking-at (concat flagged-regexp ".*"))
(format "%d/" (1+ (count-matches flagged-regexp
(point-min) (point))))
""))
nb-flagged)
'face 'buffer-menu-mode-line-flagged)))))))
(defface buffer-menu-mode-line-marked
'((t (:foreground "Blue")))
"*Face for marked number in mode line `mode-name' for Dired buffers."
:group 'Buffer-Menu-Plus :group 'font-lock-highlighting-faces)
(defface buffer-menu-mode-line-flagged
'((t (:foreground "Red")))
"*Face for flagged number in mode line `mode-name' for Dired buffers."
:group 'Buffer-Menu-Plus :group 'font-lock-highlighting-faces)
(if (> emacs-major-version 22)
(add-hook 'Buffer-menu-mode-hook 'buffer-menu-nb-marked-in-mode-name)
(add-hook 'buffer-menu-mode-hook 'buffer-menu-nb-marked-in-mode-name)))
(provide 'buff-menu+)