unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* patch for buff-menu.el enhancements
@ 2007-07-09 23:52 Drew Adams
  2007-07-10 16:02 ` Luc Teirlinck
  2007-07-15 17:42 ` Drew Adams
  0 siblings, 2 replies; 7+ messages in thread
From: Drew Adams @ 2007-07-09 23:52 UTC (permalink / raw)
  To: Emacs-Devel

[-- Attachment #1: Type: text/plain, Size: 2508 bytes --]

Attached is a patch for buff-menu.el that provides some
enhancements for *Buffer List* (`C-x C-b').  Some of these
are similar to the enhancements I sent recently for Dired.
Some of them (e.g. click to change sort direction) are
similar to behavior provided by Windows Explorer.

To try this out with emacs -Q, load a patched copy of
buff-menu.el, and then eval each of these three sexps, the
last one using `C-M-x' (I don't know of another way for you
to override the pre-existing definition of face
`buffer-menu-buffer'):

(setq Buffer-menu-mode-map nil)
(setq Buffer-menu-sort-column 1)

;; Eval this one explicitly with C-M-x:
(custom-declare-face 'buffer-menu-buffer
  '((t (:foreground "Blue")))
  "Face used to highlight buffer names in the buffer menu."
  :group 'Buffer-menu)


Features:

1. A new column, Time, which is the time that a buffer was
   last accessed (displayed).

2. You can sort up or down by clicking any column
   heading. The sorted column and its sort order (ascending
   or descending) are indicated by highlighting of the
   column header (underlining or overlining, respectively).

3. Clicking column heading `CRM' sorts the buffers by time
   of first access (visit). This is not the same thing as a
   descending sort of Time, which is the time of last access
   (display). If you have many buffers (especially if they
   have similar names), sorting by one of these columns can
   be useful.

4. A mouse popup menu (`mouse-3'), providing these items:

   * Select Buffer
   * Unmark Buffer
   * Mark to Save Buffer
   * Mark to Delete Buffer
   * Mark as Modified/Unmodified
   * Execute: Save/Delete Marked Buffers

5. Command `buffer-menu' was redefined so that:

   * A prefix argument zero or less means list buffers
     alphabetically.

   * A prefix argument zero or more means list only file
     buffers.

6. The buffer-menu buffer (`*Buffer List*') is font-lock
   highlighted:

   * Each field of the buffer uses a different face: CRM,
     Buffer, Size, Mode, File.

   * Each mark uses a different face (Save, Delete,
     Read-Only, Mark, Current).

7. The buffer lines have the `mouse-face' property on the
   whole line, so you can click it anywhere.

8. Command `Buffer-menu-select' (`v') uses `pop-to-buffer'
   when the *Buffer List* window is `window-dedicated-p'.

9. Different kinds of buffers (directory, `*...*' name,
    normal) are highlighted differently, and the buffer name
    is also highlighted specially when you mark or flag a
    buffer.

[-- Attachment #2: diff-buff-menu-2007-07-09.diff --]
[-- Type: application/octet-stream, Size: 45693 bytes --]

cd c:/drews-lisp-20/cvs-lisp/
diff -c -b "c:/Emacs-22.1/lisp/buff-menu.el" "c:/drews-lisp-20/cvs-lisp/buff-menu-CVS-patched-2007-07-09.el"
*** c:/Emacs-22.1/lisp/buff-menu.el	Fri May 25 05:43:30 2007
--- c:/drews-lisp-20/cvs-lisp/buff-menu-CVS-patched-2007-07-09.el	Mon Jul  9 15:56:08 2007
***************
*** 64,85 ****
  ;; Put buffer *Buffer List* into proper mode right away
  ;; so that from now on even list-buffers is enough to get a buffer menu.
  
  (defgroup Buffer-menu nil
    "Show a menu of all buffers in a buffer."
    :group 'tools
    :group 'convenience)
  
- (defcustom Buffer-menu-use-header-line t
-   "*Non-nil means to use an immovable header-line."
-   :type 'boolean
-   :group 'Buffer-menu)
- 
  (defface buffer-menu-buffer
!   '((t (:weight bold)))
    "Face used to highlight buffer names in the buffer menu."
    :group 'Buffer-menu)
  (put 'Buffer-menu-buffer 'face-alias 'buffer-menu-buffer)
  
  (defcustom Buffer-menu-buffer+size-width 26
    "*How wide to jointly make the buffer name and size columns."
    :type 'number
--- 64,178 ----
  ;; Put buffer *Buffer List* into proper mode right away
  ;; so that from now on even list-buffers is enough to get a buffer menu.
  
+ (eval-when-compile (require 'cl)) ;; case
+ 
  (defgroup Buffer-menu nil
    "Show a menu of all buffers in a buffer."
    :group 'tools
    :group 'convenience)
  
  (defface buffer-menu-buffer
!   '((t (:foreground "Blue")))
    "Face used to highlight buffer names in the buffer menu."
    :group 'Buffer-menu)
+ (defvar buffer-menu-buffer-name 'buffer-menu-buffer-name)
  (put 'Buffer-menu-buffer 'face-alias 'buffer-menu-buffer)
  
+ (defface buffer-menu-headings
+   '((t (:foreground "Orange" :background "DarkGreen")))
+   "Face used for headings in *Buffer List* buffer."
+   :group 'Buffer-menu)
+ (defvar buffer-menu-headings 'buffer-menu-headings)
+ 
+ (defface buffer-menu-current-buffer
+   '((t (:foreground "Red" :background "Aquamarine")))
+   "Face used for current buffer mark in *Buffer List* buffer."
+   :group 'Buffer-menu)
+ (defvar buffer-menu-current-buffer 'buffer-menu-current-buffer)
+ 
+ (defface buffer-menu-view-mark
+   '((t (:foreground "Red" :background "Aquamarine")))
+   "Face used for buffers to view mark (>) in *Buffer List* buffer."
+   :group 'Buffer-menu)
+ (defvar buffer-menu-view-mark 'buffer-menu-view-mark)
+ 
+ (defface buffer-menu-star-buffer
+   '((t (:foreground "DarkBlue")))
+   "Face used for buffers named \"*...*\"in *Buffer List* buffer."
+   :group 'Buffer-menu)
+ (defvar buffer-menu-star-buffer 'buffer-menu-star-buffer)
+ 
+ (defface buffer-menu-directory-buffer
+   '((t (:foreground "Blue" :background "LightBlue")))
+   "Face used for directory buffers in *Buffer List* buffer."
+   :group 'Buffer-menu)
+ (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)
+ (defvar buffer-menu-marked-buffer 'buffer-menu-marked-buffer)
+ 
+ (defface buffer-menu-flagged-buffer
+   '((t (:foreground "Red")))
+   "Face used for buffers marked with `D' in *Buffer List* buffer."
+   :group 'Buffer-menu)
+ (defvar buffer-menu-flagged-buffer 'buffer-menu-flagged-buffer)
+ 
+ (defface buffer-menu-delete-mark
+   '((t (:foreground "Aquamarine" :background "Red")))
+   "Face used for buffers to delete mark (D) in *Buffer List* buffer."
+   :group 'Buffer-menu)
+ (defvar buffer-menu-delete-mark 'buffer-menu-delete-mark)
+ 
+ (defface buffer-menu-save-mark
+   '((t (:foreground "Orange" :background "Blue")))
+   "Face used for buffers to save mark (S) in *Buffer List* buffer."
+   :group 'Buffer-menu)
+ (defvar buffer-menu-save-mark 'buffer-menu-save-mark)
+ 
+ (defface buffer-menu-modified-mark
+   '((t (:foreground "DarkOrange")))
+   "Face used for modified buffers mark (*) in *Buffer List* buffer."
+   :group 'Buffer-menu)
+ (defvar buffer-menu-modified-mark 'buffer-menu-modified-mark)
+ 
+ (defface buffer-menu-read-only-mark
+   '((t (:foreground "Yellow")))
+   "Face used for read-only buffers mark (%) in *Buffer List* buffer."
+   :group 'Buffer-menu)
+ (defvar buffer-menu-read-only-mark 'buffer-menu-read-only-mark)
+ 
+ (defface buffer-menu-mode
+   '((t (:foreground "DarkGreen")))
+   "Face used for buffer modes in *Buffer List* buffer."
+   :group 'Buffer-menu)
+ (defvar buffer-menu-mode 'buffer-menu-mode)
+ 
+ (defface buffer-menu-size
+   '((t (:foreground "DarkRed")))
+   "Face used for buffer sizes in *Buffer List* buffer."
+   :group 'Buffer-menu)
+ (defvar buffer-menu-size 'buffer-menu-size)
+ 
+ (defface buffer-menu-time
+   '((t (:foreground "DarkGoldenrod4")))
+   "Face used for buffer time in *Buffer List* buffer."
+   :group 'Buffer-menu)
+ (defvar buffer-menu-time 'buffer-menu-time)
+ 
+ (defface buffer-menu-file-name
+   '((t (:foreground "DarkMagenta")))
+   "Face used for file names in *Buffer List* buffer."
+   :group 'Buffer-menu)
+ (defvar buffer-menu-file-name 'buffer-menu-file-name)
+ 
+ (defcustom Buffer-menu-use-header-line t
+   "*Non-nil means to use an immovable header-line."
+   :type 'boolean
+   :group 'Buffer-menu)
+ 
  (defcustom Buffer-menu-buffer+size-width 26
    "*How wide to jointly make the buffer name and size columns."
    :type 'number
***************
*** 100,115 ****
    :group 'Buffer-menu
    :version "22.1")
  
! ;; This should get updated & resorted when you click on a column heading
! (defvar Buffer-menu-sort-column nil
!   "Which column to sort the menu on.
! Use 2 to sort by buffer names, or 5 to sort by file names.
! nil means sort by visited order (the default).")
  
  (defconst Buffer-menu-buffer-column 4)
  
! (defvar Buffer-menu-mode-map nil
!   "Local keymap for `Buffer-menu-mode' buffers.")
  
  (defvar Buffer-menu-files-only nil
    "Non-nil if the current buffer-menu lists only file buffers.
--- 193,235 ----
    :group 'Buffer-menu
    :version "22.1")
  
! (defvar Buffer-menu-sort-column 1
!   "Which column to sort the buffer menu on.
! Sorted by (1) visit, (2) buffer, (3) size, (4) time, (5) mode, (6) file.
! This is updated when you click a column heading.")
! 
! (defvar buffer-menu-font-lock-keywords
!   (list
!    (list "^\\(CRM.*\\)" 1 'buffer-menu-headings)
!    (list "^....\\(.*[^ \t\n]\\)[ \t]+[0-9]+[ \t]+\\(.* \\(AM\\|PM\\)\\)?\\([^/\n]+\\)"
!              (list 1 'buffer-menu-buffer-name)) ; Default buffer name
!    (list "^....\\(.*[^ \t\n]\\)[ \t]+[0-9]+[ \t]+[a-zA-Z :0-9]*[ \t]+Dired"
!          1 'buffer-menu-directory-buffer t t) ; Directory buffer name
!    (list "^....\\(\\*.*[^ \t\n]\\*\\)[ \t]+" 1 'buffer-menu-star-buffer t t) ; Star buffer name
!    (list "^.*[ \t][0-9]+[ \t]+\\(.* \\(AM\\|PM\\)\\)?\\([^\n]+\\)"
!          (list 1 'buffer-menu-time t t) ; Time
!          (list 3 'buffer-menu-mode t t)) ; Mode
!    (list "^.*[ \t]\\([0-9]+\\)[ \t]+[^/\n]+" 1 'buffer-menu-size t t) ; Size
!    (list "^.*[ \t][0-9]+[ \t]+[^/\n]+[ \t\n]\\(\\([~]\\|\\([a-zA-Z]:\\)\\)*/.*\\)$"
!          1 'buffer-menu-file-name t t) ; File name
!    (list "^\\([.]\\)" 1 'buffer-menu-current-buffer t t) ; Current buffer mark (.)
!    (list "^\\(>\\)" 1 'buffer-menu-view-mark t t) ; To view mark (>)
!    (list "^>...\\(.*[^ \t\n]\\)[ \t]+[0-9]+[ \t]+\\(.* \\(AM\\|PM\\)\\)?\\([^/\n]+\\)"
!          (list 1 'buffer-menu-marked-buffer 'prepend t)) ; Buffer name when marked (>)
!    (list "^D...\\(.*[^ \t\n]\\)[ \t]+[0-9]+[ \t]+\\(.* \\(AM\\|PM\\)\\)?\\([^/\n]+\\)"
!          (list 1 'buffer-menu-flagged-buffer t t)) ; Buffer name when flagged (D)
!    (list "^\\(D\\)" 1 'buffer-menu-delete-mark t t) ; Deletion flag (D)
!    (list "^..\\(S\\)" 1 'buffer-menu-save-mark t t) ; Save flag (S)
!    (list "^..\\([*]\\)" 1 'buffer-menu-modified-mark t t) ; Buffer-modified-p (*)
!    (list "^.\\(%\\)" 1 'buffer-menu-read-only-mark t t) ; Read-only-p (%)
!    ) "*Expressions to highlight in Buffer Menu mode.")
! 
! (defvar Buffer-menu-overlay nil
!   "Overlay to highlight line of buffer during popup of `mouse-3' menu.")
  
  (defconst Buffer-menu-buffer-column 4)
  
! (defvar Buffer-menu-mode-map nil "Local keymap for `Buffer-menu-mode' buffers.")
  
  (defvar Buffer-menu-files-only nil
    "Non-nil if the current buffer-menu lists only file buffers.
***************
*** 157,162 ****
--- 277,284 ----
    (define-key Buffer-menu-mode-map "T" 'Buffer-menu-toggle-files-only)
    (define-key Buffer-menu-mode-map [mouse-2] 'Buffer-menu-mouse-select)
    (define-key Buffer-menu-mode-map [follow-link] 'mouse-face)
+   (define-key Buffer-menu-mode-map [down-mouse-3] 'Buffer-menu-mouse-3-menu)
+   (define-key Buffer-menu-mode-map [mouse-3] 'ignore)
  )
  
  ;; Buffer Menu mode is suitable only for specially formatted data.
***************
*** 165,209 ****
  (defun Buffer-menu-mode ()
    "Major mode for editing a list of buffers.
  Each line describes one of the buffers in Emacs.
! Letters do not insert themselves; instead, they are commands.
  \\<Buffer-menu-mode-map>
! \\[Buffer-menu-mouse-select] -- select buffer you click on, in place of the buffer menu.
! \\[Buffer-menu-this-window] -- select current line's buffer in place of the buffer menu.
! \\[Buffer-menu-other-window] -- select that buffer in another window,
!   so the buffer menu buffer remains visible in its window.
  \\[Buffer-menu-view] -- select current line's buffer, but in view-mode.
  \\[Buffer-menu-view-other-window] -- select that buffer in
    another window, in view-mode.
- \\[Buffer-menu-switch-other-window] -- make another window display that buffer.
- \\[Buffer-menu-mark] -- mark current line's buffer to be displayed.
- \\[Buffer-menu-select] -- select current line's buffer.
-   Also show buffers marked with m, in other windows.
- \\[Buffer-menu-1-window] -- select that buffer in full-frame window.
- \\[Buffer-menu-2-window] -- select that buffer in one window,
-   together with buffer selected before this one in another window.
- \\[Buffer-menu-visit-tags-table] -- visit-tags-table this buffer.
- \\[Buffer-menu-not-modified] -- clear modified-flag on that buffer.
- \\[Buffer-menu-save] -- mark that buffer to be saved, and move down.
- \\[Buffer-menu-delete] -- mark that buffer to be deleted, and move down.
- \\[Buffer-menu-delete-backwards] -- mark that buffer to be deleted, and move up.
- \\[Buffer-menu-execute] -- delete or save marked buffers.
- \\[Buffer-menu-unmark] -- remove all kinds of marks from current line.
-   With prefix argument, also move up one line.
- \\[Buffer-menu-backup-unmark] -- back up a line and remove marks.
- \\[Buffer-menu-toggle-read-only] -- toggle read-only status of buffer on this line.
- \\[Buffer-menu-revert] -- update the list of buffers.
  \\[Buffer-menu-toggle-files-only] -- toggle whether the menu displays only file buffers.
! \\[Buffer-menu-bury] -- bury the buffer listed on this line."
    (kill-all-local-variables)
    (use-local-map Buffer-menu-mode-map)
    (setq major-mode 'Buffer-menu-mode)
    (setq mode-name "Buffer Menu")
!   (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)
    (setq buffer-read-only t)
    (run-mode-hooks 'buffer-menu-mode-hook))
  
  ;; This function exists so we can make the doc string of Buffer-menu-mode
--- 287,376 ----
  (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.)
! 
! If `Buffer-menu-use-header-line' is non-nil, 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.  Note that sorting by column `CRM' depends
! on the value of option `Buffer-menu-use-frame-buffer-list'.  (Column
! sorting is not available in Emacs prior to release 22.)
! 
! Press `mouse-3' for a popup menu that provides most of the functions
! listed below.
! 
! Display 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] -- select current line's buffer, but in view-mode.
  \\[Buffer-menu-view-other-window] -- select that buffer in
    another window, in view-mode.
  \\[Buffer-menu-toggle-files-only] -- toggle whether the menu displays only file buffers.
! 
! Mark/Unmark 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.
! 
! Save/Delete buffers:
! -------------------
! \\[Buffer-menu-execute]\t-- Save / Delete marked buffers (marks `S', `D').
! 
! Miscellaneous:
! -------------
! \\[Buffer-menu-revert] -- 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)
    (setq mode-name "Buffer Menu")
!   (save-excursion
!     (goto-char (point-min))
!     (unless Buffer-menu-use-header-line (forward-line 2)) ; First two lines are title, unless use header line.
!     (while (not (eobp))
!       (put-text-property (point) (save-excursion (end-of-line) (point)) '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)
    (setq buffer-read-only t)
+   (save-window-excursion
+     (save-excursion
+       (pop-to-buffer "*Buffer List*")
+       (setq font-lock-defaults '(buffer-menu-font-lock-keywords t))
+       (turn-on-font-lock)
+       (when (and (fboundp 'fit-frame) (one-window-p t)) (fit-frame))
+       (raise-frame)))
    (run-mode-hooks 'buffer-menu-mode-hook))
  
  ;; This function exists so we can make the doc string of Buffer-menu-mode
***************
*** 269,293 ****
  \f
  (defun buffer-menu (&optional arg)
    "Make a menu of buffers so you can save, delete or select them.
! With argument, show only buffers that are visiting files.
! Type ? after invocation to get help on commands available.
! Type q to remove the buffer menu from the display.
! 
! The first column shows `>' for a buffer you have
! marked to be displayed, `D' for one you have marked for
! deletion, and `.' for the current buffer.
! 
! The C column has a `.' for the buffer from which you came.
! The R column has a `%' if the buffer is read-only.
! The M column has a `*' if it is modified,
! or `S' if you have marked it for saving.
  After this come the buffer name, its size in characters,
! its major mode, and the visited file name (if any)."
    (interactive "P")
! ;;;  (setq Buffer-menu-window-config (current-window-configuration))
!   (switch-to-buffer (list-buffers-noselect arg))
!   (message
!    "Commands: d, s, x, u; f, o, 1, 2, m, v; ~, %%; q to quit; ? for help."))
  
  (defun buffer-menu-other-window (&optional arg)
    "Display a list of buffers in another window.
--- 436,478 ----
  \f
  (defun buffer-menu (&optional arg)
    "Make a menu of buffers so you can save, delete or select them.
! 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.)
! 
! 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.
! 
! The C column 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.
! The R column shows `%' if the buffer is read-only.
! The M column shows `*' if the buffer is modified, or `S' if you have
!   marked it for saving.
  After this come the buffer name, its size in characters,
! its major mode, and the visited file name (if any).
! 
! Type `?' in buffer \"*Buffer List*\" to get help on available commands.
! 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))) ; Sort lines after header.
!         (let ((buffer-read-only nil))
!           (goto-char (point-min))
!           (unless Buffer-menu-use-header-line (forward-line 2)) ; Header.
!           (forward-char 4)
!           (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"))
  
  (defun buffer-menu-other-window (&optional arg)
    "Display a list of buffers in another window.
***************
*** 397,403 ****
      (forward-line)))
  
  (defun Buffer-menu-execute ()
!   "Save and/or delete buffers marked with \\<Buffer-menu-mode-map>\\[Buffer-menu-save] or \\<Buffer-menu-mode-map>\\[Buffer-menu-delete] commands."
    (interactive)
    (save-excursion
      (Buffer-menu-beginning)
--- 582,592 ----
      (forward-line)))
  
  (defun Buffer-menu-execute ()
!   "Save or delete buffers marked `S' or `D', respectively.
! Buffers can be marked using 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)
    (save-excursion
      (Buffer-menu-beginning)
***************
*** 429,437 ****
  
  (defun Buffer-menu-select ()
    "Select this line's buffer; also display buffers marked with `>'.
! You can mark buffers with the \\<Buffer-menu-mode-map>\\[Buffer-menu-mark] command.
! This command deletes and replaces all the previously existing windows
! in the selected frame."
    (interactive)
    (let ((buff (Buffer-menu-buffer t))
  	(menu (current-buffer))
--- 618,626 ----
  
  (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]'.
! If the window is `window-dedicated-p', then another window is used;
! else, all windows previously in the frame are replaced by this one."
    (interactive)
    (let ((buff (Buffer-menu-buffer t))
  	(menu (current-buffer))
***************
*** 444,462 ****
  	(delete-char -1)
  	(insert ?\s))
        (or (eq tem buff) (memq tem others) (setq others (cons tem others))))
!     (setq others (nreverse others)
! 	  tem (/ (1- (frame-height)) (1+ (length others))))
      (delete-other-windows)
      (switch-to-buffer buff)
!     (or (eq menu buff)
! 	(bury-buffer menu))
      (if (equal (length others) 0)
  	(progn
  ;;;	  ;; Restore previous window configuration before displaying
  ;;;	  ;; selected buffers.
  ;;;	  (if Buffer-menu-window-config
! ;;;	      (progn
! ;;;		(set-window-configuration Buffer-menu-window-config)
  ;;;		(setq Buffer-menu-window-config nil)))
  	  (switch-to-buffer buff))
        (while others
--- 633,657 ----
  	(delete-char -1)
  	(insert ?\s))
        (or (eq tem buff) (memq tem others) (setq others (cons tem others))))
!     (setq others (nreverse others))
!     (cond ((window-dedicated-p (selected-window)) ; Can't split dedicated win.
!            (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
  ;;;              ;; Restore previous window configuration before displaying
  ;;;              ;; selected buffers.
  ;;;              (if Buffer-menu-window-config
! ;;;                  (progn (set-window-configuration
! ;;;                            Buffer-menu-window-config)
  ;;;                         (setq Buffer-menu-window-config nil)))
                   (switch-to-buffer buff))
               (while others
***************
*** 464,471 ****
  	(other-window 1)
  	(switch-to-buffer (car others))
  	(setq others (cdr others)))
!       (other-window 1)  			;back to the beginning!
! )))
  
  
  \f
--- 659,665 ----
                 (other-window 1)
                 (switch-to-buffer (car others))
                 (setq others (cdr others)))
!              (other-window 1))))))
  
  
  \f
***************
*** 561,573 ****
          (insert line))
        (message "Buried buffer moved to the end"))))
  
- 
  (defun Buffer-menu-view ()
    "View this line's buffer in View mode."
    (interactive)
    (view-buffer (Buffer-menu-buffer t)))
  
- 
  (defun Buffer-menu-view-other-window ()
    "View this line's buffer in View mode in another window."
    (interactive)
--- 755,765 ----
***************
*** 615,627 ****
  	  size))
  
  (defun Buffer-menu-sort (column)
!   "Sort the buffer menu by COLUMN."
    (interactive "P")
    (when column
      (setq column (prefix-numeric-value column))
!     (if (< column 2) (setq column 2))
!     (if (> column 5) (setq column 5)))
!   (setq Buffer-menu-sort-column column)
    (let (buffer-read-only l buf m1 m2)
      (save-excursion
        (Buffer-menu-beginning)
--- 807,823 ----
  	  size))
  
  (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 l buf m1 m2)
      (save-excursion
        (Buffer-menu-beginning)
***************
*** 650,656 ****
  	    (forward-char 2)
  	    (delete-char 1)
  	    (insert m2)))
! 	(forward-line)))))
  
  (defun Buffer-menu-sort-by-column (&optional e)
    "Sort the buffer menu by the column clicked on."
--- 846,861 ----
  	    (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")))
  
  (defun Buffer-menu-sort-by-column (&optional e)
    "Sort the buffer menu by the column clicked on."
***************
*** 675,691 ****
      map)
    "Local keymap for Buffer menu sort buttons.")
  
! (defun Buffer-menu-make-sort-button (name column)
!   (if (equal column Buffer-menu-sort-column) (setq column nil))
    (propertize name
! 	      'column column
! 	      'help-echo (concat
! 			  (if Buffer-menu-use-header-line
! 			      "mouse-1, mouse-2: sort by "
! 			    "mouse-2, RET: sort by ")
! 			  (if column (downcase name) "visited order"))
  	      'mouse-face 'highlight
! 	      'keymap Buffer-menu-sort-button-map))
  
  (defun list-buffers-noselect (&optional files-only buffer-list)
    "Create and return a buffer with a list of names of existing buffers.
--- 880,913 ----
      map)
    "Local keymap for Buffer menu sort buttons.")
  
! (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)
!       (setq 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)))
  
  (defun list-buffers-noselect (&optional files-only buffer-list)
    "Create and return a buffer with a list of names of existing buffers.
***************
*** 700,713 ****
    (let* ((old-buffer (current-buffer))
  	 (standard-output standard-output)
  	 (mode-end (make-string (- Buffer-menu-mode-width 2) ?\s))
! 	 (header (concat "CRM "
  			 (Buffer-menu-buffer+size
  			  (Buffer-menu-make-sort-button "Buffer" 2)
  			  (Buffer-menu-make-sort-button "Size" 3))
  			 "  "
! 			 (Buffer-menu-make-sort-button "Mode" 4) mode-end
! 			 (Buffer-menu-make-sort-button "File" 5) "\n"))
! 	 list desired-point)
      (when Buffer-menu-use-header-line
        (let ((pos 0))
  	;; Turn whitespace chars in the header into stretch specs so
--- 922,936 ----
    (let* ((old-buffer (current-buffer))
  	 (standard-output standard-output)
  	 (mode-end (make-string (- Buffer-menu-mode-width 2) ?\s))
! 	 (header (concat (Buffer-menu-make-sort-button "CRM" 1) " "
  			 (Buffer-menu-buffer+size
  			  (Buffer-menu-make-sort-button "Buffer" 2)
  			  (Buffer-menu-make-sort-button "Size" 3))
  			 "  "
!                          (Buffer-menu-make-sort-button "Time" 4) "             "
! 			 (Buffer-menu-make-sort-button "Mode" 5) mode-end
! 			 (Buffer-menu-make-sort-button "File" 6) "\n"))
! 	 list desired-point name buffer-time mode file)
      (when Buffer-menu-use-header-line
        (let ((pos 0))
  	;; Turn whitespace chars in the header into stretch specs so
***************
*** 718,725 ****
  			     ;; Assume fixed-size chars in the buffer.
  			     (list 'space :align-to pos)
  			     header)))
-       ;; Try to better align the one-char headers.
-       (put-text-property 0 3 'face 'fixed-pitch header)
        ;; Add a "dummy" leading space to align the beginning of the header
        ;; line with the beginning of the text (rather than with the left
        ;; scrollbar or the left fringe).  --Stef
--- 941,946 ----
***************
*** 730,747 ****
        (erase-buffer)
        (setq standard-output (current-buffer))
        (unless Buffer-menu-use-header-line
          ;; Use U+2014 (EM DASH) to underline if possible, else use ASCII
          ;; (i.e. U+002D, HYPHEN-MINUS).
! 	(let ((underline (if (char-displayable-p ?\u2014) ?\u2014 ?-)))
  	  (insert header
  		  (apply 'string
  			 (mapcar (lambda (c)
  				   (if (memq c '(?\n ?\s)) c underline))
  				 header)))))
        ;; Collect info for every buffer we're interested in.
        (dolist (buffer (or buffer-list
  			  (buffer-list
! 			   (when Buffer-menu-use-frame-buffer-list
  			     (selected-frame)))))
  	(with-current-buffer buffer
  	  (let ((name (buffer-name))
--- 951,974 ----
        (erase-buffer)
        (setq standard-output (current-buffer))
        (unless Buffer-menu-use-header-line
+         ;; Only Emacs > 21 has `char-displayable' and U+2014.
          ;; Use U+2014 (EM DASH) to underline if possible, else use ASCII
          ;; (i.e. U+002D, HYPHEN-MINUS).
! 	(let ((underline (if (and (fboundp 'char-displayable-p)
!                                   (char-displayable-p ?\u2014))
!                              ?\u2014    ; EM dash
!                            ?-)))        ; regular dash
  	  (insert header
  		  (apply 'string
  			 (mapcar (lambda (c)
  				   (if (memq c '(?\n ?\s)) c underline))
  				 header)))))
+       (if buffer-list
+           (setq list buffer-list)
          ;; Collect info for every buffer we're interested in.
          (dolist (buffer (or buffer-list
                              (buffer-list
!                              (and Buffer-menu-use-frame-buffer-list
                                    (selected-frame)))))
            (with-current-buffer buffer
              (let ((name (buffer-name))
***************
*** 754,761 ****
  			  (and files-only (not file))
  			  (string= name "*Buffer List*")))
  	      ;; Otherwise output info.
! 	      (let ((mode (concat (format-mode-line mode-name nil nil buffer)
! 				  (if mode-line-process
  				      (format-mode-line mode-line-process
  							nil nil buffer))))
  		    (bits (string
--- 981,996 ----
                              (and files-only (not file))
                              (string= name "*Buffer List*")))
                  ;; Otherwise output info.
!                 (let (;; Need to record two values for time: numerical time value, for
!                       ;; sorting, and string time value, for display.
!                       (buffer-time (cons (or (float-time buffer-display-time) 0)
!                                          (if buffer-display-time
!                                              (format-time-string
!                                               "%_3a %_2k:%02M:%02S %_2p"
!                                               buffer-display-time)
!                                            "               ")))
!                       (mode (concat (format-mode-line mode-name nil nil buffer)
!                                     (and mode-line-process
                                           (format-mode-line mode-line-process
                                                             nil nil buffer))))
                        (bits (string
***************
*** 788,818 ****
  			   (setq file "*Info History*"))
  			  ((eq file 'toc)
  			   (setq file "*Info TOC*"))
! 			  ((not (stringp file))  ;; avoid errors
  			   (setq file nil))
  			  (t
  			   (setq file (concat "("
  					      (file-name-nondirectory file)
  					      ")"
  					      Info-current-node)))))))
! 		(push (list buffer bits name (buffer-size) mode file)
  		      list))))))
!       ;; Preserve the original buffer-list ordering, just in case.
!       (setq list (nreverse list))
        ;; Place the buffers's info in the output buffer, sorted if necessary.
        (dolist (buffer
! 	       (if Buffer-menu-sort-column
  		   (sort list
! 			 (if (eq Buffer-menu-sort-column 3)
  			     (lambda (a b)
! 			       (< (nth Buffer-menu-sort-column a)
  				  (nth Buffer-menu-sort-column b)))
  			   (lambda (a b)
! 			     (string< (nth Buffer-menu-sort-column a)
! 				      (nth Buffer-menu-sort-column b)))))
! 		 list))
! 	(if (eq (car buffer) old-buffer)
! 	    (setq desired-point (point)))
  	(insert (cadr buffer)
  		;; Put the buffer name into a text property
  		;; so we don't have to extract it from the text.
--- 1023,1064 ----
                                (setq file "*Info History*"))
                               ((eq file 'toc)
                                (setq file "*Info TOC*"))
!                              ((not (stringp file));; avoid errors
                                (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))))))
!         ;; Preserve original list order (by reversing).
!         ;; Flip it if Buffer-menu-sort-column = -1.
!         (unless (eq -1 Buffer-menu-sort-column) (setq list (nreverse list))))
        ;; Place the buffers's info in the output buffer, sorted if necessary.
        (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) ; Size
!                                  (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) ; Time (value)
!                                  (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)
                  ;; Put the buffer name into a text property
                  ;; so we don't have to extract it from the text.
***************
*** 825,848 ****
  					   mouse-face highlight
  					   help-echo "mouse-2: select this buffer"))
  		"  "
! 		(if (> (length (nth 4 buffer)) Buffer-menu-mode-width)
! 		    (substring (nth 4 buffer) 0 Buffer-menu-mode-width)
! 		  (nth 4 buffer)))
! 	(when (nth 5 buffer)
  	  (indent-to (+ Buffer-menu-buffer-column Buffer-menu-buffer+size-width
! 			Buffer-menu-mode-width 4) 1)
! 	  (princ (abbreviate-file-name (nth 5 buffer))))
  	(princ "\n"))
        (Buffer-menu-mode)
        (when Buffer-menu-use-header-line
  	(setq header-line-format header))
!       ;; DESIRED-POINT doesn't have to be set; it is not when the
        ;; current buffer is not displayed for some reason.
!       (and desired-point
! 	   (goto-char desired-point))
        (setq Buffer-menu-files-only files-only)
        (set-buffer-modified-p nil)
        (current-buffer))))
  
  ;; arch-tag: e7dfcfc9-6cb2-46e4-bf55-8ef1936d83c6
  ;;; buff-menu.el ends here
--- 1071,1245 ----
                                             mouse-face highlight
                                             help-echo "mouse-2: select this buffer"))
                  "  "
!                 (cdr (nth 4 buffer)) "  " ; Time
!                 (if (> (length (nth 5 buffer)) Buffer-menu-mode-width) ; Mode
!                     (substring (nth 5 buffer) 0 Buffer-menu-mode-width)
!                   (nth 5 buffer)))
!         (when (nth 6 buffer)
            (indent-to (+ Buffer-menu-buffer-column Buffer-menu-buffer+size-width
!                         Buffer-menu-mode-width 17 4) 1)
!           (princ (abbreviate-file-name (nth 6 buffer))))
          (princ "\n"))
        (Buffer-menu-mode)
        (when Buffer-menu-use-header-line
          (setq header-line-format header))
!       ;; DESIRED-POINT doesn't have to be set; it is not set when the
        ;; current buffer is not displayed for some reason.
!       (goto-char (or desired-point (point-min)))
        (setq Buffer-menu-files-only files-only)
        (set-buffer-modified-p nil)
        (current-buffer))))
  \f
+ 
+ (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))
+               (save-excursion
+                 (setq bol (progn (beginning-of-line) (point)))
+                 (setq eol (progn (end-of-line) (point))))
+               (if Buffer-menu-overlay   ; Don't recreate if exists.
+                   (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)))
+               ;; Nil if mouse is not on a buffer name.
+               (and temp (buffer-name temp)))))) ; temp no longer used.
+     (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)
+                   '("--")               ; Separator: next not buffer-specific.
+                   '("Execute: Save/Delete Marked Buffers" .
+                     Buffer-menu-mouse-execute))
+                (list "" '("Execute: Save/Delete Marked Buffers" .
+                           Buffer-menu-mouse-execute)))))))
+       (when Buffer-menu-overlay (delete-overlay Buffer-menu-overlay))
+       (and selection (call-interactively selection)))))
+ 
+ (defun Buffer-menu-mouse-unmark (event)
+   "Cancel all requested operations on buffer."
+   (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)))
+     (goto-char (posn-point (event-end event)))
+     (beginning-of-line)
+     (if (looking-at " [-M]")            ;header lines
+         (ding)
+       (let* ((mod (buffer-modified-p buffer))
+              (readonly (save-excursion (set-buffer buffer) buffer-read-only))
+              (buffer-read-only nil))
+         (delete-char 3)
+         (insert (if readonly (if mod " *%" "  %") (if mod " * " "   ")))))
+     (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]")              ;header lines
+       (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]")              ;header lines
+       (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)))
+   (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 (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))))))))
+ 
  ;; arch-tag: e7dfcfc9-6cb2-46e4-bf55-8ef1936d83c6
  ;;; buff-menu.el ends here

Diff finished at Mon Jul 09 16:13:02

[-- Attachment #3: Type: text/plain, Size: 142 bytes --]

_______________________________________________
Emacs-devel mailing list
Emacs-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/emacs-devel

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: patch for buff-menu.el enhancements
  2007-07-09 23:52 patch for buff-menu.el enhancements Drew Adams
@ 2007-07-10 16:02 ` Luc Teirlinck
  2007-07-10 17:25   ` Drew Adams
  2007-07-15 17:42 ` Drew Adams
  1 sibling, 1 reply; 7+ messages in thread
From: Luc Teirlinck @ 2007-07-10 16:02 UTC (permalink / raw)
  To: drew.adams; +Cc: emacs-devel

Drew Adams wrote:

   ! If `Buffer-menu-use-header-line' is non-nil, you can click a column=0A=
   ! heading to sort by that column.

_Without_ your patch, you can do that even if
`Buffer-menu-use-header-line' is nil.  Disabling the feature in that
case is definitely not improvement; in fact I consider it a bug.

I do not understand _why_ you want to reimplement the existing feature,
which seems to work perfectly fine to me and also plays well with
autoreverting the buffer menu.  (I did not check if your
reimplementation does.)

Sincerely,

Luc.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* RE: patch for buff-menu.el enhancements
  2007-07-10 16:02 ` Luc Teirlinck
@ 2007-07-10 17:25   ` Drew Adams
  2007-07-10 21:21     ` Mathias Dahl
  0 siblings, 1 reply; 7+ messages in thread
From: Drew Adams @ 2007-07-10 17:25 UTC (permalink / raw)
  To: Luc Teirlinck; +Cc: emacs-devel

>    ! If `Buffer-menu-use-header-line' is non-nil, you can click a
>    ! column heading to sort by that column.
>
> _Without_ your patch, you can do that even if
> `Buffer-menu-use-header-line' is nil.  Disabling the feature in that
> case is definitely not improvement; in fact I consider it a bug.

I disabled nothing of the kind. The doc string was incorrect, sorry. Here's
the correction: Please remove the phrase "If `Buffer-menu-use-header-line'
is non-nil, ".  Thanks for noticing that.

> I do not understand _why_ you want to reimplement the existing feature,
> which seems to work perfectly fine to me and also plays well with
> autoreverting the buffer menu.  (I did not check if your
> reimplementation does.)

Please try it.  I don't think I did what you suggest.  There is no problem
reverting the buffer. Reverting changes nothing; the current sort is
maintained.

FWIW, I proposed essentially this same patch back in 2004. I updated it for
the latest version of buff-menu.el. See, for example, these threads:

* 2004/10/16, "buff-menu.el - minor enhancement to sort
  columns up or down"
* 2004/11/19, "buff-menu.el header line"
* 2005/11/28, "Buffer listing in multiple frames/ttys"
 (related wrt sorting)

The only changes from vanilla Emacs wrt column sorting that my patch makes
are those I mentioned, in particular, (1) being able to sort in either
direction, (2) indicating the current sort column and sort direction with an
overline/underline of the column heading, and (3) being able to also sort
column `CRM' (one direction of which is the default sort).

For those who use Windows Explorer, you will recognize this
click-column-header sorting; you probably use it many times a day. IMO, it
is one of the most useful features of Windows Explorer. I think we should do
the same thing for Dired.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: patch for buff-menu.el enhancements
  2007-07-10 17:25   ` Drew Adams
@ 2007-07-10 21:21     ` Mathias Dahl
  2007-07-10 21:56       ` Drew Adams
  0 siblings, 1 reply; 7+ messages in thread
From: Mathias Dahl @ 2007-07-10 21:21 UTC (permalink / raw)
  To: Drew Adams; +Cc: Luc Teirlinck, emacs-devel

> For those who use Windows Explorer, you will recognize this
> click-column-header sorting; you probably use it many times a day. IMO, it
> is one of the most useful features of Windows Explorer. I think we should do
> the same thing for Dired.

Speaking of sorting in Dired, I really like this simple hack, which I
use many times per day:

;;; dired-sort-map.el --- in Dired: press s then s, x, t or n to sort
by Size, eXtension, Time or Name

;; Copyright (C) 2002 by Free Software Foundation, Inc.

;; Author: Patrick Anderson
;; Version: 1

;; This file 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.

;; This file 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 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:

;;; inspired by Francis J. Wright's dired-sort-menu.el

;install:
;this file in your load path

;add
; (require 'dired-sort-map)
;to your .emacs file

(defvar dired-sort-map (make-sparse-keymap))

(add-hook 'dired-mode-hook '(lambda () (define-key dired-mode-map "s"
dired-sort-map)))
(add-hook 'dired-mode-hook '(lambda () (define-key dired-sort-map "s"
'(lambda () "sort by Size" (interactive) (dired-sort-other (concat
dired-listing-switches "S"))))))
(add-hook 'dired-mode-hook '(lambda () (define-key dired-sort-map "x"
'(lambda () "sort by eXtension" (interactive) (dired-sort-other
(concat dired-listing-switches "X"))))))
(add-hook 'dired-mode-hook '(lambda () (define-key dired-sort-map "t"
'(lambda () "sort by Time" (interactive) (dired-sort-other (concat
dired-listing-switches "t"))))))
(add-hook 'dired-mode-hook '(lambda () (define-key dired-sort-map "n"
'(lambda () "sort by Name" (interactive) (dired-sort-other (concat
dired-listing-switches ""))))))

(provide 'dired-sort-map)

;;; dired-sort-map.el ends here

/Mathias

^ permalink raw reply	[flat|nested] 7+ messages in thread

* RE: patch for buff-menu.el enhancements
  2007-07-10 21:21     ` Mathias Dahl
@ 2007-07-10 21:56       ` Drew Adams
  2007-07-11 10:00         ` Mathias Dahl
  0 siblings, 1 reply; 7+ messages in thread
From: Drew Adams @ 2007-07-10 21:56 UTC (permalink / raw)
  To: Mathias Dahl; +Cc: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 843 bytes --]

> > For those who use Windows Explorer, you will recognize this
> > click-column-header sorting; you probably use it many times a
> > day. IMO, it is one of the most useful features of Windows
> > Explorer. I think we should do the same thing for Dired.
>
> Speaking of sorting in Dired, I really like this simple hack,
> which I use many times per day...
> ;;; inspired by Francis J. Wright's dired-sort-menu.el

And speaking of FJW's dired-sort-menu.el, I was going to propose that we add
that as well ;-)  I use it all the time. (I have some minor tweaks of that
too: http://www.emacswiki.org/cgi-bin/wiki/dired-sort-menu%2b.el.)

It's good to have both keyboard bindings and a sort menu, IMO. The menu
includes many sort possibilities, far more than one would like to remember
keys for. Attached is a screenshot of most of the menu, FYI.


[-- Attachment #2: throw-dired-sort-menu.png --]
[-- Type: image/png, Size: 12800 bytes --]

[-- Attachment #3: Type: text/plain, Size: 142 bytes --]

_______________________________________________
Emacs-devel mailing list
Emacs-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/emacs-devel

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: patch for buff-menu.el enhancements
  2007-07-10 21:56       ` Drew Adams
@ 2007-07-11 10:00         ` Mathias Dahl
  0 siblings, 0 replies; 7+ messages in thread
From: Mathias Dahl @ 2007-07-11 10:00 UTC (permalink / raw)
  To: Drew Adams; +Cc: emacs-devel

> And speaking of FJW's dired-sort-menu.el, I was going to propose that we add
> that as well ;-)  I use it all the time. (I have some minor tweaks of that
> too: http://www.emacswiki.org/cgi-bin/wiki/dired-sort-menu%2b.el.)

I have it installed too but I don't use it nearly as much as the key
bindings hack mentioned above. I don't use the mouse much. However, it
has been very useful when I have needed to do more advanced sorting. I
am sure this is very useful for many users.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* RE: patch for buff-menu.el enhancements
  2007-07-09 23:52 patch for buff-menu.el enhancements Drew Adams
  2007-07-10 16:02 ` Luc Teirlinck
@ 2007-07-15 17:42 ` Drew Adams
  1 sibling, 0 replies; 7+ messages in thread
From: Drew Adams @ 2007-07-15 17:42 UTC (permalink / raw)
  To: Emacs-Devel

> From: Drew Adams Sent: Monday, July 09, 2007 4:53 PM
> Attached is a patch for buff-menu.el that provides some
> enhancements for *Buffer List* (`C-x C-b').  Some of these
> are similar to the enhancements I sent recently for Dired.
> Some of them (e.g. click to change sort direction) are
> similar to behavior provided by Windows Explorer.

Was anything decided about this?

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2007-07-15 17:42 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-07-09 23:52 patch for buff-menu.el enhancements Drew Adams
2007-07-10 16:02 ` Luc Teirlinck
2007-07-10 17:25   ` Drew Adams
2007-07-10 21:21     ` Mathias Dahl
2007-07-10 21:56       ` Drew Adams
2007-07-11 10:00         ` Mathias Dahl
2007-07-15 17:42 ` Drew Adams

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).