Ibuffer is an advanced replacement for BufferMenu, which lets you operate on buffers much in the same manner as Dired. The most important Ibuffer features are highlighting and various alternate layouts. Ibuffer is part of Emacs since version 22.
You could use the following key binding to start using it:
(global-set-key (kbd "C-x C-b") 'ibuffer)
‘M-s a C-s’
- Do incremental search in the marked buffers.‘M-s a C-M-s’
- Isearch for regexp in the marked buffers.‘U’
- Replace by regexp in each of the marked buffers.‘Q’
- Query replace in each of the marked buffers.‘I’
- As above, with a regular expression.‘0’
- Run occur on the marked buffers.Here’s how to hide all buffers starting with an asterisk.
(require 'ibuf-ext) (add-to-list 'ibuffer-never-show-predicates "^\\*")
Also try ibuffer’s “limiting” feature (‘/’
), which allows you to just view a subset of your buffers.
Ibuffer can show you the differences between an unsaved buffer and the file on disk with `=’.
Ibuffer has an excellent implementation of Gnus-style grouping. Try this:
(setq ibuffer-saved-filter-groups (quote (("default" ("dired" (mode . dired-mode)) ("perl" (mode . cperl-mode)) ("erc" (mode . erc-mode)) ("planner" (or (name . "^\\*Calendar\\*$") (name . "^diary$") (mode . muse-mode))) ("emacs" (or (name . "^\\*scratch\\*$") (name . "^\\*Messages\\*$"))) ("gnus" (or (mode . message-mode) (mode . bbdb-mode) (mode . mail-mode) (mode . gnus-group-mode) (mode . gnus-summary-mode) (mode . gnus-article-mode) (name . "^\\.bbdb$") (name . "^\\.newsrc-dribble")))))))
(add-hook 'ibuffer-mode-hook (lambda () (ibuffer-switch-to-saved-filter-groups "default")))
Then M-x dired
then M-x ibuffer
and you should see your dired buffer in a group. Open more of them and they all endup in there. This means that when browsing buffers you can skip over the items you are used to seeing. Anything not grouped goes at the bottom of the ibuffer buffer. – PhilJackson
It looks as though the default filterings are as follows:
predicate content size-lt size-gt filename name used-mode mode
Since filename can work for any part of the path, if you filter on a partial (or complete) directory, anything you have open from the directory is now grouped:
("journal" (filename . "/personal/journal/"))
I’m not familiar with gnus, and have been unsuccessful tracking written docs on filtering – I extracted the above from a reading of ibuf-ext.el
and then onto the contents of ibuffer-filtering-alist
. If there is anything out there, somebody please add it in, and edit this note. --OtherMichael
The last two lines of the ibuffer provide some information about each column. These two lines may be hidden by setting the ibuffer-display-summary
variable to nil. The first two lines of the ibuffer are headers describing the contents of the columns. I don’t find these headers so useful and didn’t find a quick way to turn them off. So here is an advice that does the trick:
(defadvice ibuffer-update-title-and-summary (after remove-column-titles) (save-excursion (set-buffer "*Ibuffer*") (toggle-read-only 0) (goto-char 1) (search-forward "-\n" nil t) (delete-region 1 (point)) (let ((window-min-height 1)) ;; save a little screen estate (shrink-window-if-larger-than-buffer)) (toggle-read-only))) (ad-activate 'ibuffer-update-title-and-summary)
This extension to ibuffer-mode can dynamically create filter groups for the listed files’ version-control trees, and show their status (e.g. up-to-date, modified etc.).
This extension (based on ibuffer-vc) to ibuffer-mode can dynamically create filter groups for TRAMP buffers.
I’m not quite sure where to add this, but to be able to sort by pathname (thereby grouping file buffers with dired buffers). PeterMielke
Ibuffer should now use ‘dired-directory’
when appropriate. If you are able/willing to sign an assignment (see LegalMatters) then please send a patch defining an Ibuffer ‘filename’
sorter that falls back to ‘dired-directory’
for dired buffers – JohnPaulWallington.
Was it eventually added to Emacs? – DianeMurray
(defun my-ibuffer-hook () ;; add another sorting method for ibuffer (allow the grouping of ;; filenames and dired buffers (ibuffer-define-sorter pathname (:documentation "Sort the buffers by their pathname." :description "path") (string-lessp (with-current-buffer (car a) (or buffer-file-name (if (eq major-mode 'dired-mode) (expand-file-name dired-directory)) ;; so that all non pathnames are at the end "~")) (with-current-buffer (car b) (or buffer-file-name (if (eq major-mode 'dired-mode) (expand-file-name dired-directory)) ;; so that all non pathnames are at the end "~")))) ;; add key binding (define-key ibuffer-mode-map (kbd "s p") 'ibuffer-do-sort-by-pathname)) (add-hook 'ibuffer-mode-hook 'my-ibuffer-hook)
I modified the above, works with GNU Emacs 22.0.92.1, should this work? --DavidBoon
(define-ibuffer-sorter filename-or-dired "Sort the buffers by their pathname." (:description "filenames plus dired") (string-lessp (with-current-buffer (car a) (or buffer-file-name (if (eq major-mode 'dired-mode) (expand-file-name dired-directory)) ;; so that all non pathnames are at the end "~")) (with-current-buffer (car b) (or buffer-file-name (if (eq major-mode 'dired-mode) (expand-file-name dired-directory)) ;; so that all non pathnames are at the end "~")))) (define-key ibuffer-mode-map (kbd "s p") 'ibuffer-do-sort-by-filename-or-dired)
I didn’t really want a new filter; I just wanted the existing filename filter to also include dired buffers. Re-defining that filter in my init file as follows did the trick:
;; Enable ibuffer-filter-by-filename to filter on directory names too. (eval-after-load "ibuf-ext" '(define-ibuffer-filter filename "Toggle current view to buffers with file or directory name matching QUALIFIER." (:description "filename" :reader (read-from-minibuffer "Filter by file/directory name (regexp): ")) (ibuffer-awhen (or (buffer-local-value 'buffer-file-name buf) (buffer-local-value 'dired-directory buf)) (string-match qualifier it))))
I don’t like default “Size” column, so I write a human readable column instead of original one. – coldnew
;; Use human readable Size column instead of original one (define-ibuffer-column size-h (:name "Size" :inline t) (cond ((> (buffer-size) 1000000) (format "%7.1fM" (/ (buffer-size) 1000000.0))) ((> (buffer-size) 100000) (format "%7.0fk" (/ (buffer-size) 1000.0))) ((> (buffer-size) 1000) (format "%7.1fk" (/ (buffer-size) 1000.0))) (t (format "%8d" (buffer-size))))) ;; Modify the default ibuffer-formats (setq ibuffer-formats '((mark modified read-only " " (name 18 18 :left :elide) " " (size-h 9 -1 :right) " " (mode 16 16 :left :elide) " " filename-and-process)))
I added a little more code to the above code so that the bottom summary line also showed total size in human readable form.
(defun ajv/human-readable-file-sizes-to-bytes (string) "Convert a human-readable file size into bytes." (interactive) (cond ((string-suffix-p "G" string t) (* 1000000000 (string-to-number (substring string 0 (- (length string) 1))))) ((string-suffix-p "M" string t) (* 1000000 (string-to-number (substring string 0 (- (length string) 1))))) ((string-suffix-p "K" string t) (* 1000 (string-to-number (substring string 0 (- (length string) 1))))) (t (string-to-number (substring string 0 (- (length string) 1)))) ) ) (defun ajv/bytes-to-human-readable-file-sizes (bytes) "Convert number of bytes to human-readable file size." (interactive) (cond ((> bytes 1000000000) (format "%10.1fG" (/ bytes 1000000000.0))) ((> bytes 100000000) (format "%10.0fM" (/ bytes 1000000.0))) ((> bytes 1000000) (format "%10.1fM" (/ bytes 1000000.0))) ((> bytes 100000) (format "%10.0fk" (/ bytes 1000.0))) ((> bytes 1000) (format "%10.1fk" (/ bytes 1000.0))) (t (format "%10d" bytes))) ) ;; Use human readable Size column instead of original one (define-ibuffer-column size-h (:name "Size" :inline t :summarizer (lambda (column-strings) (let ((total 0)) (dolist (string column-strings) (setq total ;; like, ewww ... (+ (float (ajv/human-readable-file-sizes-to-bytes string)) total))) (ajv/bytes-to-human-readable-file-sizes total))) ;; :summarizer nil ) (ajv/bytes-to-human-readable-file-sizes (buffer-size))) ;; Modify the default ibuffer-formats (setq ibuffer-formats '((mark modified read-only locked " " (name 20 20 :left :elide) " " (size-h 11 -1 :right) " " (mode 16 16 :left :elide) " " filename-and-process) (mark " " (name 16 -1) " " filename)))
I have some buffer groups that i prefer do be collapsed by default. Since i found no way to have this working i adviced ibuffer like this:
(setq mp/ibuffer-collapsed-groups (list "Helm" "*Internal*")) (defadvice ibuffer (after collapse-helm) (dolist (group mp/ibuffer-collapsed-groups) (progn (goto-char 1) (when (search-forward (concat "[ " group " ]") (point-max) t) (progn (move-beginning-of-line nil) (ibuffer-toggle-filter-group) ) ) ) ) (goto-char 1) (search-forward "[ " (point-max) t) ) (ad-activate 'ibuffer)
Another way to do this is to add the names of the groups to be hidden to ‘ibuffer-hidden-filter-groups’
in ‘ibuffer-mode-hook’
:
(add-hook 'ibuffer-mode-hook (lambda () (ibuffer-switch-to-saved-filter-groups "default") (setq ibuffer-hidden-filter-groups (list "Helm" "*Internal*")) (ibuffer-update nil t) ) )
With this, when you press ‘up’
or `down` to the top/bottom of IBuffer, the cursor wraps around to the bottom/top, so you can continue from there.
(defun ibuffer-previous-line () (interactive) (previous-line) (if (<= (line-number-at-pos) 2) (goto-line (- (count-lines (point-min) (point-max)) 2))))
(defun ibuffer-next-line () (interactive) (next-line) (if (>= (line-number-at-pos) (- (count-lines (point-min) (point-max)) 1)) (goto-line 3))) (define-key ibuffer-mode-map (kbd "<up>") 'ibuffer-previous-line) (define-key ibuffer-mode-map (kbd "<down>") 'ibuffer-next-line)
– kuanyui
With this improvement you do not need to hard code the line numbers, you just need copy, compile and run. Moreover, the keys ‘up’
and ‘down’
do the same thing but they skip the names of the filtered groups, and you can move to the beginning or the end of a group with ‘left’
and ‘right’
.
(defun ibuffer-advance-motion (direction) (forward-line direction) (beginning-of-line) (if (not (get-text-property (point) 'ibuffer-filter-group-name)) t (ibuffer-skip-properties '(ibuffer-filter-group-name) direction) nil))
(defun ibuffer-previous-line (&optional arg) "Move backwards ARG lines, wrapping around the list if necessary." (interactive "P") (or arg (setq arg 1)) (let (err1 err2) (while (> arg 0) (cl-decf arg) (setq err1 (ibuffer-advance-motion -1) err2 (if (not (get-text-property (point) 'ibuffer-title)) t (goto-char (point-max)) (beginning-of-line) (ibuffer-skip-properties '(ibuffer-summary ibuffer-filter-group-name) -1) nil))) (and err1 err2))) (defun ibuffer-next-line (&optional arg) "Move forward ARG lines, wrapping around the list if necessary." (interactive "P") (or arg (setq arg 1)) (let (err1 err2) (while (> arg 0) (cl-decf arg) (setq err1 (ibuffer-advance-motion 1) err2 (if (not (get-text-property (point) 'ibuffer-summary)) t (goto-char (point-min)) (beginning-of-line) (ibuffer-skip-properties '(ibuffer-summary ibuffer-filter-group-name ibuffer-title) 1) nil))) (and err1 err2)))
(defun brust/ibuffer-next-header () (interactive) (while (ibuffer-next-line))) (defun brust/ibuffer-previous-header () (interactive) (while (ibuffer-previous-line)))
(define-key ibuffer-mode-map (kbd "<up>") 'ibuffer-previous-line) (define-key ibuffer-mode-map (kbd "<down>") 'ibuffer-next-line) (define-key ibuffer-mode-map (kbd "<right>") 'ibuffer-previous-header) (define-key ibuffer-mode-map (kbd "<left>") 'ibuffer-next-header)
– brust
With Icicles, you can use ‘M-s i’
in Ibuffer to search all marked buffers and possibly replace search hits. You have available all of the Icicles Search features, including accessing search hits directly, in any order.
Ibuffer is part of Emacs since version 22.
If you don’t have Ibuffer, you can get it from GIT:ibuffer.el (there’s also a probably out-of-date project at gna.org). Here’s how to install it:
(global-set-key (kbd "C-x C-b") 'ibuffer) (autoload 'ibuffer "ibuffer" "List buffers." t)